2
0

SUnit.st 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  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. RunningTestContext subclass: #ErroringTestContext
  54. instanceVariableNames: ''
  55. package: 'SUnit'!
  56. !ErroringTestContext methodsFor: 'private'!
  57. exception: anException ifNotAsync: aBlock
  58. anException signal
  59. ! !
  60. !ErroringTestContext class methodsFor: 'instance creation'!
  61. testCase: aTestCase
  62. ^self
  63. testCase: aTestCase
  64. result: TestResult new
  65. finished: []
  66. ! !
  67. Object subclass: #TestCase
  68. instanceVariableNames: 'testSelector asyncTimeout context'
  69. package: 'SUnit'!
  70. !TestCase methodsFor: 'accessing'!
  71. context: aRunningTestContext
  72. context := aRunningTestContext
  73. !
  74. selector
  75. ^testSelector
  76. !
  77. setTestSelector: aSelector
  78. testSelector := aSelector
  79. ! !
  80. !TestCase methodsFor: 'async'!
  81. async: aBlock
  82. | c |
  83. self mustBeAsync: '#async'.
  84. c := context.
  85. ^[ self isAsync ifTrue: [ c execute: aBlock ]]
  86. !
  87. finished
  88. self mustBeAsync: '#finished'.
  89. asyncTimeout := nil
  90. !
  91. graceTime: millis
  92. asyncTimeout ifNotNil: [ asyncTimeout clearTimeout ].
  93. asyncTimeout := true. "to allow async:"
  94. asyncTimeout :=
  95. (self async: [ self assert: false description: 'SUnit grace time exhausted' ])
  96. valueWithTimeout: millis
  97. !
  98. isAsync
  99. ^asyncTimeout notNil
  100. !
  101. mustBeAsync: aString
  102. self isAsync ifFalse: [ self error: aString, ' used without prior #graceTime:' ]
  103. ! !
  104. !TestCase methodsFor: 'private'!
  105. signalFailure: aString
  106. TestFailure new
  107. messageText: aString;
  108. signal
  109. ! !
  110. !TestCase methodsFor: 'running'!
  111. performTest
  112. asyncTimeout := nil.
  113. self perform: self selector
  114. !
  115. runCase
  116. "Runs a test case in isolated context, leaking all errors."
  117. (ErroringTestContext testCase: self) start
  118. !
  119. setUp
  120. !
  121. tearDown
  122. ! !
  123. !TestCase methodsFor: 'testing'!
  124. assert: aBoolean
  125. self assert: aBoolean description: 'Assertion failed'
  126. !
  127. assert: aBoolean description: aString
  128. aBoolean ifFalse: [self signalFailure: aString]
  129. !
  130. assert: expected equals: actual
  131. ^ self assert: (expected = actual) description: 'Expected: ', expected asString, ' but was: ', actual asString
  132. !
  133. deny: aBoolean
  134. self assert: aBoolean not
  135. !
  136. should: aBlock
  137. self assert: aBlock value
  138. !
  139. should: aBlock raise: anExceptionClass
  140. self assert: ([aBlock value. false]
  141. on: anExceptionClass
  142. do: [:ex | true])
  143. !
  144. shouldnt: aBlock raise: anExceptionClass
  145. self assert: ([aBlock value. true]
  146. on: anExceptionClass
  147. do: [:ex | false])
  148. ! !
  149. !TestCase class methodsFor: 'accessing'!
  150. allTestSelectors
  151. | selectors |
  152. selectors := self testSelectors.
  153. self shouldInheritSelectors ifTrue: [
  154. selectors addAll: self superclass allTestSelectors].
  155. ^selectors
  156. !
  157. buildSuite
  158. ^self allTestSelectors collect: [:each | self selector: each]
  159. !
  160. lookupHierarchyRoot
  161. ^TestCase
  162. !
  163. selector: aSelector
  164. ^self new
  165. setTestSelector: aSelector;
  166. yourself
  167. !
  168. testSelectors
  169. ^self methodDictionary keys select: [:each | each match: '^test']
  170. ! !
  171. !TestCase class methodsFor: 'testing'!
  172. isAbstract
  173. ^ self name = 'TestCase'
  174. !
  175. shouldInheritSelectors
  176. ^self ~= self lookupHierarchyRoot
  177. ! !
  178. Error subclass: #TestFailure
  179. instanceVariableNames: ''
  180. package: 'SUnit'!
  181. Object subclass: #TestResult
  182. instanceVariableNames: 'timestamp runs errors failures total'
  183. package: 'SUnit'!
  184. !TestResult methodsFor: 'accessing'!
  185. addError: anError
  186. self errors add: anError
  187. !
  188. addFailure: aFailure
  189. self failures add: aFailure
  190. !
  191. errors
  192. ^errors
  193. !
  194. failures
  195. ^failures
  196. !
  197. increaseRuns
  198. runs := runs + 1
  199. !
  200. runs
  201. ^runs
  202. !
  203. status
  204. ^self errors isEmpty
  205. ifTrue: [
  206. self failures isEmpty
  207. ifTrue: ['success']
  208. ifFalse: ['failure']]
  209. ifFalse: ['error']
  210. !
  211. timestamp
  212. ^timestamp
  213. !
  214. total
  215. ^total
  216. !
  217. total: aNumber
  218. total := aNumber
  219. ! !
  220. !TestResult methodsFor: 'initialization'!
  221. initialize
  222. super initialize.
  223. timestamp := Date now.
  224. runs := 0.
  225. errors := Array new.
  226. failures := Array new.
  227. total := 0
  228. ! !
  229. Object subclass: #TestSuiteRunner
  230. instanceVariableNames: 'suite result announcer runNextTest'
  231. package: 'SUnit'!
  232. !TestSuiteRunner methodsFor: 'accessing'!
  233. announcer
  234. ^announcer
  235. !
  236. result
  237. ^result
  238. !
  239. suite: aCollection
  240. suite := aCollection
  241. ! !
  242. !TestSuiteRunner methodsFor: 'actions'!
  243. resume
  244. runNextTest fork.
  245. announcer announce: (ResultAnnouncement new result: result)
  246. !
  247. run
  248. result total: suite size.
  249. self resume
  250. ! !
  251. !TestSuiteRunner methodsFor: 'initialization'!
  252. initialize
  253. super initialize.
  254. announcer := Announcer new.
  255. result := TestResult new.
  256. runNextTest := [ | runs | runs := result runs. runs < result total ifTrue: [ (self contextOf: runs + 1) start ]].
  257. ! !
  258. !TestSuiteRunner methodsFor: 'private'!
  259. contextOf: anInteger
  260. ^RunningTestContext testCase: (suite at: anInteger) result: result finished: [ self resume ]
  261. ! !
  262. !TestSuiteRunner class methodsFor: 'instance creation'!
  263. new
  264. self shouldNotImplement
  265. !
  266. on: aCollection
  267. ^super new suite: aCollection
  268. ! !