SUnit.st 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. Object subclass: #TestCase instanceVariableNames: 'testedClass' category: 'SUnit'! !TestCase methodsFor: 'accessing'! testedClass
  2. ^testedClass ! testedClass: aClass
  3. testedClass := aClass ! ! !TestCase methodsFor: 'private'! cleanUpInstanceVariables
  4. self class instanceVariableNames do: [ :name |
  5. name = 'testSelector' ifFalse: [
  6. self instVarAt: name put: nil ]] ! signalFailure: aString
  7. TestFailure new
  8. messageText: aString;
  9. signal ! ! !TestCase methodsFor: 'running'! setUp ! tearDown ! methods
  10. ^self class methodDictionary keys select: [:each | each match: '^test'] ! runCaseFor: aTestResult
  11. [self setUp.
  12. self performTestFor: aTestResult]
  13. on: Error
  14. do: [:ex |
  15. self tearDown.
  16. self cleanUpInstanceVariables.
  17. ex signal].
  18. self tearDown.
  19. self cleanUpInstanceVariables ! performTestFor: aResult
  20. self methods do: [:each |
  21. [[self perform: each]
  22. on: TestFailure do: [:ex | aResult addFailure: self class name, '>>', each]]
  23. on: Error do: [:ex | aResult addError: self class name, '>>', each].
  24. aResult increaseRuns] ! ! !TestCase methodsFor: 'testing'! assert: aBoolean
  25. aBoolean ifFalse: [self signalFailure: 'Assertion failed'] ! deny: aBoolean
  26. self assert: aBoolean not ! ! TestCase subclass: #ExampleTest instanceVariableNames: 'test' category: 'SUnit'! !ExampleTest methodsFor: 'not yet classified'! testFailure
  27. self deny: true
  28. ! testPasses
  29. 100000 timesRepeat: [self assert: 1 + 1 = 2] ! testError
  30. self assert: 1 foo ! ! TabWidget subclass: #ProgressBar instanceVariableNames: 'percent, progressDiv' category: 'SUnit'! !ProgressBar methodsFor: 'accessing'! percent
  31. ^percent ifNil: [0] ! percent: aNumber
  32. percent := aNumber ! ! !ProgressBar methodsFor: 'rendering'! renderOn: html
  33. html div
  34. class: 'progress_bar';
  35. with: [
  36. html div
  37. class: 'progress';
  38. style: 'width:', self percent asString, '%'] ! ! !ProgressBar methodsFor: 'updating'! updatePercent: aNumber
  39. self percent: aNumber.
  40. self update ! ! Error subclass: #TestFailure instanceVariableNames: '' category: 'SUnit'! TabWidget subclass: #TestRunner instanceVariableNames: 'selectedCategories, categoriesList, selectedClasses, classesList, selectedMethods, progressBar, methodsList, result, statusDiv' category: 'SUnit'! !TestRunner methodsFor: 'accessing'! label
  41. ^'[Test runner]'
  42. ! categories
  43. | categories |
  44. categories := Array new.
  45. self allClasses do: [:each |
  46. (categories includes: each category) ifFalse: [
  47. categories add: each category]].
  48. ^categories sort ! classes
  49. ^(self allClasses
  50. select: [:each | self selectedCategories includes: each category])
  51. sort: [:a :b | a name > b name] ! selectedCategories
  52. ^selectedCategories ifNil: [selectedCategories := Array new] ! allClasses
  53. ^TestCase allSubclasses ! selectedClasses
  54. ^selectedClasses ifNil: [selectedClasses := Array new] ! progressBar
  55. ^progressBar ifNil: [progressBar := ProgressBar new] ! selectedMethods
  56. ^selectedMethods ifNil: [self selectedClasses collect: [:each |
  57. each methodDictionary keys select: [:key | key beginsWith: 'test' ]]] ! statusInfo
  58. ^self printTotal, self printPasses, self printErrors, self printFailures ! result
  59. ^result ! failedMethods
  60. self result failures collect: [:each |
  61. html li
  62. class: 'failures';
  63. with: each] ! ! !TestRunner methodsFor: 'actions'! selectAllCategories
  64. self categories do: [:each |
  65. (selectedCategories includes: each) ifFalse: [
  66. self selectedCategories add: each]].
  67. self
  68. updateCategoriesList;
  69. updateClassesList ! toggleCategory: aCategory
  70. (self isSelectedCategory: aCategory)
  71. ifFalse: [selectedCategories add: aCategory]
  72. ifTrue: [selectedCategories remove: aCategory].
  73. self
  74. updateCategoriesList;
  75. updateClassesList ! toggleClass: aClass
  76. (self isSelectedClass: aClass)
  77. ifFalse: [selectedClasses add: aClass]
  78. ifTrue: [selectedClasses remove: aClass].
  79. self
  80. updateClassesList ! selectAllClasses
  81. self classes do: [:each |
  82. (selectedClasses includes: each) ifFalse: [
  83. self selectedClasses add: each]].
  84. self
  85. updateCategoriesList;
  86. updateClassesList ! run: aCollection
  87. result := TestResult new.
  88. self
  89. updateStatusDiv;
  90. updateMethodsList.
  91. self progressBar updatePercent: 0.
  92. result total: (aCollection inject: 0 into: [:acc :each | acc + each methods size]).
  93. aCollection do: [:each |
  94. [each runCaseFor: result.
  95. self progressBar updatePercent: result runs / result total * 100.
  96. self updateStatusDiv.
  97. self updateMethodsList] valueWithTimeout: 100]. ! ! !TestRunner methodsFor: 'initialization'! initialize
  98. super initialize.
  99. result := TestResult new ! ! !TestRunner methodsFor: 'printing'! printErrors
  100. ^self result errors size asString , ' errors, ' ! printFailures
  101. ^self result failures size asString, ' failures' ! printPasses
  102. ^(((self result total) - (self result errors size + (self result failures size))) asString) , ' passes, ' ! printTotal
  103. ^self result total asString, ' runs, ' ! ! !TestRunner methodsFor: 'rendering'! renderBoxOn: html
  104. self
  105. renderCategoriesOn: html;
  106. renderClassesOn: html;
  107. renderResultsOn: html ! renderButtonsOn: html
  108. html button
  109. with: 'Run selected';
  110. onClick: [self run: (self selectedClasses collect: [:each | each new])]
  111. ! renderCategoriesOn: html
  112. categoriesList := html ul class: 'jt_column sunit categories'.
  113. self updateCategoriesList ! renderClassesOn: html
  114. classesList := html ul class: 'jt_column sunit classes'.
  115. self updateClassesList ! renderResultsOn: html
  116. statusDiv := html div.
  117. html with: self progressBar.
  118. methodsList := html ul class: 'jt_column sunit methods'.
  119. self updateMethodsList.
  120. self updateStatusDiv ! renderFailuresOn: html
  121. self result failures do: [:each |
  122. html li
  123. class: 'failures';
  124. with: each] ! renderErrorsOn: html
  125. self result errors do: [:each |
  126. html li
  127. class: 'errors';
  128. with: each] ! ! !TestRunner methodsFor: 'testing'! canBeClosed
  129. ^true
  130. ! isSelectedClass: aClass
  131. ^(self selectedClasses includes: aClass) ! isSelectedCategory: aCategory
  132. ^(self selectedCategories includes: aCategory) ! ! !TestRunner methodsFor: 'updating'! updateCategoriesList
  133. categoriesList contents: [:html |
  134. html li
  135. class: 'all';
  136. with: 'All';
  137. onClick: [self selectAllCategories].
  138. self categories do: [:each || li |
  139. li := html li.
  140. (self selectedCategories includes: each) ifTrue: [
  141. li class: 'selected'].
  142. li
  143. with: each;
  144. onClick: [self toggleCategory: each]]] ! updateClassesList
  145. classesList contents: [:html |
  146. (self selectedCategories isEmpty) ifFalse: [
  147. html li
  148. class: 'all';
  149. with: 'All';
  150. onClick: [self selectAllClasses]].
  151. self classes do: [:each || li |
  152. li := html li.
  153. (self selectedClasses includes: each) ifTrue: [
  154. li class: 'selected'].
  155. li
  156. with: each name;
  157. onClick: [self toggleClass: each]]] ! updateMethodsList
  158. methodsList contents: [:html |
  159. self renderFailuresOn: html.
  160. self renderErrorsOn: html] ! updateStatusDiv
  161. statusDiv class: 'sunit status ', result status.
  162. statusDiv contents: [:html |
  163. html span with: self statusInfo] ! ! Object subclass: #TestResult instanceVariableNames: 'timestamp, runs, errors, failures, total' category: 'SUnit'! !TestResult methodsFor: 'accessing'! timestamp
  164. ^timestamp ! errors
  165. ^errors ! failures
  166. ^failures ! total
  167. ^total ! total: aNumber
  168. total := aNumber ! addError: anError
  169. self errors add: anError ! addFailure: aFailure
  170. self failures add: aFailure ! runs
  171. ^runs ! increaseRuns
  172. runs := runs + 1 ! status
  173. ^self errors isEmpty
  174. ifTrue: [
  175. self failures isEmpty
  176. ifTrue: ['success']
  177. ifFalse: ['failure']]
  178. ifFalse: ['error'] ! ! !TestResult methodsFor: 'initialization'! initialize
  179. super initialize.
  180. timestamp := Date now.
  181. runs := 0.
  182. errors := Array new.
  183. failures := Array new.
  184. total := 0 ! ! TestCase subclass: #ExampleTest2 instanceVariableNames: '' category: 'SUnit'! !ExampleTest2 methodsFor: 'not yet classified'! testPasses
  185. 100000 timesRepeat: [self assert: 1 + 1 = 2] ! ! TestCase subclass: #ExampleTest3 instanceVariableNames: '' category: 'SUnit'! !ExampleTest3 methodsFor: 'not yet classified'! testPasses
  186. 100000 timesRepeat: [self assert: 1 + 1 = 2] ! !