SUnit.st 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. Smalltalk current createPackage: 'SUnit' properties: #{}!
  2. Object subclass: #ResultAnnouncement
  3. instanceVariableNames: 'result'
  4. package: 'SUnit'!
  5. !ResultAnnouncement methodsFor: 'accessing'!
  6. result
  7. ^result
  8. !
  9. result: aTestResult
  10. result := aTestResult
  11. ! !
  12. Object subclass: #RunningTestContext
  13. instanceVariableNames: 'finished testCase result step'
  14. package: 'SUnit'!
  15. !RunningTestContext methodsFor: 'accessing'!
  16. finished: aBlock
  17. finished := aBlock
  18. !
  19. result: aTestResult
  20. result := aTestResult
  21. !
  22. testCase: aTestCase
  23. testCase := aTestCase
  24. ! !
  25. !RunningTestContext methodsFor: 'private'!
  26. exception: anException ifNotAsync: aBlock
  27. testCase isAsync
  28. ifTrue: [ step := [ testCase finished. anException signal ]]
  29. ifFalse: [ aBlock value ]
  30. ! !
  31. !RunningTestContext methodsFor: 'running'!
  32. execute: aBlock
  33. step := aBlock.
  34. [ step isNil ] whileFalse: [
  35. testCase context: self.
  36. [[[ step
  37. ensure: [ testCase context: nil. step := nil. testCase isAsync ifFalse: [ testCase tearDown ]]]
  38. on: TestFailure do: [:ex | self exception: ex ifNotAsync: [ result addFailure: testCase]]]
  39. on: Error do: [:ex | self exception: ex ifNotAsync: [ result addError: testCase]]]
  40. ensure: [ testCase isAsync ifFalse: [ result increaseRuns. finished value ]]]
  41. !
  42. start
  43. self execute: [ testCase setUp. testCase performTest ]
  44. ! !
  45. !RunningTestContext class methodsFor: 'instance creation'!
  46. testCase: aTestCase result: aTestResult finished: aBlock
  47. ^self new
  48. testCase: aTestCase;
  49. result: aTestResult;
  50. finished: aBlock;
  51. yourself
  52. ! !
  53. Object subclass: #TestCase
  54. instanceVariableNames: 'testSelector asyncTimeout context'
  55. package: 'SUnit'!
  56. !TestCase methodsFor: 'accessing'!
  57. context: aRunningTestContext
  58. context := aRunningTestContext
  59. !
  60. selector
  61. ^testSelector
  62. !
  63. setTestSelector: aSelector
  64. testSelector := aSelector
  65. ! !
  66. !TestCase methodsFor: 'async'!
  67. async: aBlock
  68. | c |
  69. self mustBeAsync: '#async'.
  70. c := context.
  71. ^[ self isAsync ifTrue: [ c execute: aBlock ]]
  72. !
  73. finished
  74. self mustBeAsync: '#finished'.
  75. asyncTimeout := nil
  76. !
  77. graceTime: millis
  78. asyncTimeout := true
  79. !
  80. isAsync
  81. ^asyncTimeout notNil
  82. !
  83. mustBeAsync: aString
  84. self isAsync ifFalse: [ self error: aString, ' used without prior #graceTime:' ]
  85. ! !
  86. !TestCase methodsFor: 'private'!
  87. signalFailure: aString
  88. TestFailure new
  89. messageText: aString;
  90. signal
  91. ! !
  92. !TestCase methodsFor: 'running'!
  93. performTest
  94. asyncTimeout := nil.
  95. self perform: self selector
  96. !
  97. runCase
  98. [ self setUp.
  99. self performTest ] ensure: [
  100. self tearDown ]
  101. !
  102. setUp
  103. !
  104. tearDown
  105. ! !
  106. !TestCase methodsFor: 'testing'!
  107. assert: aBoolean
  108. self assert: aBoolean description: 'Assertion failed'
  109. !
  110. assert: aBoolean description: aString
  111. aBoolean ifFalse: [self signalFailure: aString]
  112. !
  113. assert: expected equals: actual
  114. ^ self assert: (expected = actual) description: 'Expected: ', expected asString, ' but was: ', actual asString
  115. !
  116. deny: aBoolean
  117. self assert: aBoolean not
  118. !
  119. should: aBlock
  120. self assert: aBlock value
  121. !
  122. should: aBlock raise: anExceptionClass
  123. self assert: ([aBlock value. false]
  124. on: anExceptionClass
  125. do: [:ex | true])
  126. !
  127. shouldnt: aBlock raise: anExceptionClass
  128. self assert: ([aBlock value. true]
  129. on: anExceptionClass
  130. do: [:ex | false])
  131. ! !
  132. !TestCase class methodsFor: 'accessing'!
  133. allTestSelectors
  134. | selectors |
  135. selectors := self testSelectors.
  136. self shouldInheritSelectors ifTrue: [
  137. selectors addAll: self superclass allTestSelectors].
  138. ^selectors
  139. !
  140. buildSuite
  141. ^self allTestSelectors collect: [:each | self selector: each]
  142. !
  143. lookupHierarchyRoot
  144. ^TestCase
  145. !
  146. selector: aSelector
  147. ^self new
  148. setTestSelector: aSelector;
  149. yourself
  150. !
  151. testSelectors
  152. ^self methodDictionary keys select: [:each | each match: '^test']
  153. ! !
  154. !TestCase class methodsFor: 'testing'!
  155. isAbstract
  156. ^ self name = 'TestCase'
  157. !
  158. shouldInheritSelectors
  159. ^self ~= self lookupHierarchyRoot
  160. ! !
  161. Error subclass: #TestFailure
  162. instanceVariableNames: ''
  163. package: 'SUnit'!
  164. Object subclass: #TestResult
  165. instanceVariableNames: 'timestamp runs errors failures total'
  166. package: 'SUnit'!
  167. !TestResult methodsFor: 'accessing'!
  168. addError: anError
  169. self errors add: anError
  170. !
  171. addFailure: aFailure
  172. self failures add: aFailure
  173. !
  174. errors
  175. ^errors
  176. !
  177. failures
  178. ^failures
  179. !
  180. increaseRuns
  181. runs := runs + 1
  182. !
  183. runs
  184. ^runs
  185. !
  186. status
  187. ^self errors isEmpty
  188. ifTrue: [
  189. self failures isEmpty
  190. ifTrue: ['success']
  191. ifFalse: ['failure']]
  192. ifFalse: ['error']
  193. !
  194. timestamp
  195. ^timestamp
  196. !
  197. total
  198. ^total
  199. !
  200. total: aNumber
  201. total := aNumber
  202. ! !
  203. !TestResult methodsFor: 'initialization'!
  204. initialize
  205. super initialize.
  206. timestamp := Date now.
  207. runs := 0.
  208. errors := Array new.
  209. failures := Array new.
  210. total := 0
  211. ! !
  212. !TestResult methodsFor: 'running'!
  213. nextRunDo: aBlock
  214. "Runs aBlock with index of next run
  215. or does nothing if no more runs"
  216. ^self runs == self total
  217. ifFalse: [ aBlock value: self runs + 1 ]
  218. ! !
  219. Object subclass: #TestSuiteRunner
  220. instanceVariableNames: 'suite result announcer runNextTest'
  221. package: 'SUnit'!
  222. !TestSuiteRunner methodsFor: 'accessing'!
  223. announcer
  224. ^announcer
  225. !
  226. result
  227. ^result
  228. !
  229. suite: aCollection
  230. suite := aCollection
  231. ! !
  232. !TestSuiteRunner methodsFor: 'actions'!
  233. resume
  234. runNextTest fork.
  235. announcer announce: (ResultAnnouncement new result: result)
  236. !
  237. run
  238. result total: suite size.
  239. self resume
  240. ! !
  241. !TestSuiteRunner methodsFor: 'initialization'!
  242. initialize
  243. super initialize.
  244. announcer := Announcer new.
  245. result := TestResult new.
  246. runNextTest := [ result nextRunDo: [ :index |
  247. (RunningTestContext testCase: (suite at: index) result: result finished: [ self resume ]) start ]].
  248. ! !
  249. !TestSuiteRunner class methodsFor: 'instance creation'!
  250. new
  251. self shouldNotImplement
  252. !
  253. on: aCollection
  254. ^super new suite: aCollection
  255. ! !