SUnit.st 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. Object subclass: #TestCase
  2. instanceVariableNames: 'testedClass'
  3. category: 'SUnit'!
  4. !TestCase methodsFor: 'accessing'!
  5. testedClass
  6. ^testedClass
  7. !
  8. testedClass: aClass
  9. testedClass := aClass
  10. ! !
  11. !TestCase methodsFor: 'private'!
  12. cleanUpInstanceVariables
  13. self class instanceVariableNames do: [ :name |
  14. name = 'testSelector' ifFalse: [
  15. self instVarAt: name put: nil ]]
  16. !
  17. signalFailure: aString
  18. TestFailure new
  19. messageText: aString;
  20. signal
  21. ! !
  22. !TestCase methodsFor: 'running'!
  23. setUp
  24. !
  25. tearDown
  26. !
  27. methods
  28. ^self class methodDictionary keys select: [:each | each match: '^test']
  29. !
  30. runCaseFor: aTestResult
  31. [self setUp.
  32. self performTestFor: aTestResult]
  33. on: Error
  34. do: [:ex |
  35. self tearDown.
  36. self cleanUpInstanceVariables.
  37. ex signal].
  38. self tearDown.
  39. self cleanUpInstanceVariables
  40. !
  41. performTestFor: aResult
  42. self methods do: [:each |
  43. [[self perform: each]
  44. on: TestFailure do: [:ex | aResult addFailure: self class name, '>>', each, ': ', ex messageText]]
  45. on: Error do: [:ex | aResult addError: self class name, '>>', each, ': ', ex messageText].
  46. aResult increaseRuns]
  47. ! !
  48. !TestCase methodsFor: 'testing'!
  49. assert: aBoolean
  50. self assert: aBoolean description: 'Assertion failed'
  51. !
  52. deny: aBoolean
  53. self assert: aBoolean not
  54. !
  55. assert: expected equals: actual
  56. ^ self assert: (expected = actual) description: 'Expected: ', expected asString, ' but was: ', actual asString
  57. !
  58. assert: aBoolean description: aString
  59. aBoolean ifFalse: [self signalFailure: aString]
  60. ! !
  61. TabWidget subclass: #ProgressBar
  62. instanceVariableNames: 'percent progressDiv div'
  63. category: 'SUnit'!
  64. !ProgressBar methodsFor: 'accessing'!
  65. percent
  66. ^percent ifNil: [0]
  67. !
  68. percent: aNumber
  69. percent := aNumber
  70. ! !
  71. !ProgressBar methodsFor: 'rendering'!
  72. renderOn: html
  73. div := html div
  74. class: 'progress_bar';
  75. yourself.
  76. self renderProgressBar
  77. !
  78. renderProgressBar
  79. div contents: [:html |
  80. html div
  81. class: 'progress';
  82. style: 'width:', self percent asString, '%']
  83. ! !
  84. !ProgressBar methodsFor: 'updating'!
  85. updatePercent: aNumber
  86. self percent: aNumber.
  87. self renderProgressBar
  88. ! !
  89. Error subclass: #TestFailure
  90. instanceVariableNames: ''
  91. category: 'SUnit'!
  92. TabWidget subclass: #TestRunner
  93. instanceVariableNames: 'selectedCategories categoriesList selectedClasses classesList selectedMethods progressBar methodsList result statusDiv'
  94. category: 'SUnit'!
  95. !TestRunner methodsFor: 'accessing'!
  96. label
  97. ^'[Test runner]'
  98. !
  99. categories
  100. | categories |
  101. categories := Array new.
  102. self allClasses do: [:each |
  103. (categories includes: each category) ifFalse: [
  104. categories add: each category]].
  105. ^categories sort
  106. !
  107. classes
  108. ^(self allClasses
  109. select: [:each | self selectedCategories includes: each category])
  110. sort: [:a :b | a name > b name]
  111. !
  112. selectedCategories
  113. ^selectedCategories ifNil: [selectedCategories := Array new]
  114. !
  115. allClasses
  116. ^TestCase allSubclasses
  117. !
  118. selectedClasses
  119. ^selectedClasses ifNil: [selectedClasses := Array new]
  120. !
  121. progressBar
  122. ^progressBar ifNil: [progressBar := ProgressBar new]
  123. !
  124. selectedMethods
  125. ^selectedMethods ifNil: [self selectedClasses collect: [:each |
  126. each methodDictionary keys select: [:key | key beginsWith: 'test' ]]]
  127. !
  128. statusInfo
  129. ^self printTotal, self printPasses, self printErrors, self printFailures
  130. !
  131. result
  132. ^result
  133. !
  134. failedMethods
  135. self result failures collect: [:each |
  136. html li
  137. class: 'failures';
  138. with: each]
  139. ! !
  140. !TestRunner methodsFor: 'actions'!
  141. selectAllCategories
  142. self categories do: [:each |
  143. (selectedCategories includes: each) ifFalse: [
  144. self selectedCategories add: each]].
  145. self
  146. updateCategoriesList;
  147. updateClassesList
  148. !
  149. toggleCategory: aCategory
  150. (self isSelectedCategory: aCategory)
  151. ifFalse: [selectedCategories add: aCategory]
  152. ifTrue: [selectedCategories remove: aCategory].
  153. self
  154. updateCategoriesList;
  155. updateClassesList
  156. !
  157. toggleClass: aClass
  158. (self isSelectedClass: aClass)
  159. ifFalse: [selectedClasses add: aClass]
  160. ifTrue: [selectedClasses remove: aClass].
  161. self
  162. updateClassesList
  163. !
  164. selectAllClasses
  165. self classes do: [:each |
  166. (selectedClasses includes: each) ifFalse: [
  167. self selectedClasses add: each]].
  168. self
  169. updateCategoriesList;
  170. updateClassesList
  171. !
  172. run: aCollection
  173. result := TestResult new.
  174. self
  175. updateStatusDiv;
  176. updateMethodsList.
  177. self progressBar updatePercent: 0.
  178. result total: (aCollection inject: 0 into: [:acc :each | acc + each methods size]).
  179. aCollection do: [:each |
  180. [each runCaseFor: result.
  181. self progressBar updatePercent: result runs / result total * 100.
  182. self updateStatusDiv.
  183. self updateMethodsList] valueWithTimeout: 100].
  184. ! !
  185. !TestRunner methodsFor: 'initialization'!
  186. initialize
  187. super initialize.
  188. result := TestResult new
  189. ! !
  190. !TestRunner methodsFor: 'printing'!
  191. printErrors
  192. ^self result errors size asString , ' errors, '
  193. !
  194. printFailures
  195. ^self result failures size asString, ' failures'
  196. !
  197. printPasses
  198. ^(((self result total) - (self result errors size + (self result failures size))) asString) , ' passes, '
  199. !
  200. printTotal
  201. ^self result total asString, ' runs, '
  202. ! !
  203. !TestRunner methodsFor: 'rendering'!
  204. renderBoxOn: html
  205. self
  206. renderCategoriesOn: html;
  207. renderClassesOn: html;
  208. renderResultsOn: html
  209. !
  210. renderButtonsOn: html
  211. html button
  212. with: 'Run selected';
  213. onClick: [self run: (self selectedClasses collect: [:each | each new])]
  214. !
  215. renderCategoriesOn: html
  216. categoriesList := html ul class: 'jt_column sunit categories'.
  217. self updateCategoriesList
  218. !
  219. renderClassesOn: html
  220. classesList := html ul class: 'jt_column sunit classes'.
  221. self updateClassesList
  222. !
  223. renderResultsOn: html
  224. statusDiv := html div.
  225. html with: self progressBar.
  226. methodsList := html ul class: 'jt_column sunit methods'.
  227. self updateMethodsList.
  228. self updateStatusDiv
  229. !
  230. renderFailuresOn: html
  231. self result failures do: [:each |
  232. html li
  233. class: 'failures';
  234. with: each]
  235. !
  236. renderErrorsOn: html
  237. self result errors do: [:each |
  238. html li
  239. class: 'errors';
  240. with: each]
  241. ! !
  242. !TestRunner methodsFor: 'testing'!
  243. canBeClosed
  244. ^true
  245. !
  246. isSelectedClass: aClass
  247. ^(self selectedClasses includes: aClass)
  248. !
  249. isSelectedCategory: aCategory
  250. ^(self selectedCategories includes: aCategory)
  251. ! !
  252. !TestRunner methodsFor: 'updating'!
  253. updateCategoriesList
  254. categoriesList contents: [:html |
  255. html li
  256. class: 'all';
  257. with: 'All';
  258. onClick: [self selectAllCategories].
  259. self categories do: [:each || li |
  260. li := html li.
  261. (self selectedCategories includes: each) ifTrue: [
  262. li class: 'selected'].
  263. li
  264. with: each;
  265. onClick: [self toggleCategory: each]]]
  266. !
  267. updateClassesList
  268. classesList contents: [:html |
  269. (self selectedCategories isEmpty) ifFalse: [
  270. html li
  271. class: 'all';
  272. with: 'All';
  273. onClick: [self selectAllClasses]].
  274. self classes do: [:each || li |
  275. li := html li.
  276. (self selectedClasses includes: each) ifTrue: [
  277. li class: 'selected'].
  278. li
  279. with: each name;
  280. onClick: [self toggleClass: each]]]
  281. !
  282. updateMethodsList
  283. methodsList contents: [:html |
  284. self renderFailuresOn: html.
  285. self renderErrorsOn: html]
  286. !
  287. updateStatusDiv
  288. statusDiv class: 'sunit status ', result status.
  289. statusDiv contents: [:html |
  290. html span with: self statusInfo]
  291. ! !
  292. Object subclass: #TestResult
  293. instanceVariableNames: 'timestamp runs errors failures total'
  294. category: 'SUnit'!
  295. !TestResult methodsFor: 'accessing'!
  296. timestamp
  297. ^timestamp
  298. !
  299. errors
  300. ^errors
  301. !
  302. failures
  303. ^failures
  304. !
  305. total
  306. ^total
  307. !
  308. total: aNumber
  309. total := aNumber
  310. !
  311. addError: anError
  312. self errors add: anError
  313. !
  314. addFailure: aFailure
  315. self failures add: aFailure
  316. !
  317. runs
  318. ^runs
  319. !
  320. increaseRuns
  321. runs := runs + 1
  322. !
  323. status
  324. ^self errors isEmpty
  325. ifTrue: [
  326. self failures isEmpty
  327. ifTrue: ['success']
  328. ifFalse: ['failure']]
  329. ifFalse: ['error']
  330. ! !
  331. !TestResult methodsFor: 'initialization'!
  332. initialize
  333. super initialize.
  334. timestamp := Date now.
  335. runs := 0.
  336. errors := Array new.
  337. failures := Array new.
  338. total := 0
  339. ! !