author | Claus Gittinger <cg@exept.de> |
Fri, 08 May 2015 12:28:56 +0200 | |
changeset 610 | 756214d7dcca |
parent 608 | dd61addf0336 |
child 622 | feaff647974c |
child 655 | a949c7616b2a |
permissions | -rw-r--r-- |
608 | 1 |
"{ Encoding: utf8 }" |
2 |
||
345 | 3 |
"{ Package: 'stx:goodies/sunit' }" |
4 |
||
597 | 5 |
"{ NameSpace: Smalltalk }" |
6 |
||
345 | 7 |
TestResult subclass:#TestResultStX |
493 | 8 |
instanceVariableNames:'endTime' |
345 | 9 |
classVariableNames:'' |
10 |
poolDictionaries:'' |
|
11 |
category:'SUnit-Smalltalk/X' |
|
12 |
! |
|
13 |
||
14 |
||
500 | 15 |
!TestResultStX class methodsFor:'utilities'! |
16 |
||
17 |
sourceFilenameOfClass:aClass |
|
18 |
"that is ST/X specific" |
|
19 |
"no Smalltalk/X dialect detection needed..." |
|
20 |
||
21 |
|sourceStream testClassSourceFile| |
|
22 |
||
23 |
sourceStream := aClass sourceStream. |
|
24 |
sourceStream notNil ifTrue:[ |
|
25 |
[ |
|
26 |
sourceStream := sourceStream stream. |
|
27 |
sourceStream isFileStream ifTrue:[ |
|
28 |
testClassSourceFile := sourceStream pathName asFilename pathName. |
|
29 |
]. |
|
30 |
] ensure:[ |
|
31 |
sourceStream close. |
|
32 |
] |
|
33 |
]. |
|
34 |
^ testClassSourceFile |
|
35 |
! ! |
|
36 |
||
479 | 37 |
!TestResultStX methodsFor:'accessing'! |
38 |
||
39 |
endTime |
|
40 |
^ endTime |
|
41 |
! |
|
42 |
||
43 |
endTime:aTimestamp |
|
44 |
"sets the overall (suite) end time" |
|
45 |
||
46 |
endTime := aTimestamp. |
|
47 |
! |
|
48 |
||
482 | 49 |
executionTime |
50 |
"return the execution time (in seconds). If asked before or during a run, return nil" |
|
51 |
||
493 | 52 |
|t1 t2| |
53 |
||
54 |
(t1 := self startTime) isNil ifTrue:[^ nil]. |
|
55 |
(t2 := self endTime) isNil ifTrue:[^ nil]. |
|
56 |
^ t2 secondDeltaFrom: t1 |
|
482 | 57 |
|
58 |
" |
|
59 |
|a b| |
|
60 |
||
61 |
a := Timestamp now. |
|
62 |
Delay waitForMilliseconds:567. |
|
63 |
b := Timestamp now. |
|
64 |
b - a |
|
65 |
" |
|
66 |
! |
|
67 |
||
479 | 68 |
startTime |
493 | 69 |
^ timestamp |
479 | 70 |
! |
71 |
||
72 |
startTime:aTimestamp |
|
493 | 73 |
"sets the overall (suite) start time" |
479 | 74 |
|
493 | 75 |
timestamp := aTimestamp. |
479 | 76 |
! ! |
77 |
||
345 | 78 |
!TestResultStX methodsFor:'outcome'! |
79 |
||
500 | 80 |
printLineForContextForJavaCompatibleStackTrace:con on:aStream |
81 |
"why in java-backtrace format? |
|
82 |
Because then jenkins will be able to extract sourcefile and linenumber |
|
83 |
and generate links in the report page. |
|
84 |
I am not willing to write another plugin for this - using junit compatible format" |
|
85 |
||
597 | 86 |
|cls classSourceStream method s lineNumberOfMethod lineNumberInFile relPath methodSourcePosition| |
500 | 87 |
|
88 |
"/ used to be: |
|
89 |
"/ con printOn:aStream. |
|
90 |
||
91 |
"/ be careful: some tests generate methods on the fly, which are unbound!! |
|
92 |
"/ or even (javascript/other languages) may not have a method at all!!!! |
|
93 |
||
94 |
con fixAllLineNumbers. |
|
95 |
(method := con method) notNil ifTrue:[ |
|
96 |
cls := method mclass. |
|
97 |
cls notNil ifTrue:[ |
|
98 |
relPath := cls package copyReplaceAll:$: with:$/. |
|
593 | 99 |
relPath := relPath asUnixFilenameString. |
505 | 100 |
relPath := (relPath asFilename construct:cls theNonMetaclass classFilename) name. |
500 | 101 |
|
597 | 102 |
method isJavaMethod ifTrue:[ |
103 |
lineNumberOfMethod := method lineNumberForPC0: 0. |
|
104 |
] ifFalse:[ |
|
105 |
methodSourcePosition := method sourcePosition. |
|
106 |
methodSourcePosition notNil ifTrue:[ |
|
107 |
classSourceStream := cls sourceStream. |
|
108 |
classSourceStream notNil ifTrue:[ |
|
580
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
109 |
"/ sigh - we have the lineNumber within the method, |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
110 |
"/ and the characterPosition of the method's start. |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
111 |
"/ need to calculate the absolute lineNumber in the file |
597 | 112 |
s := LineNumberReadStream on:classSourceStream "(classSourceFile asFilename readStream)". |
580
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
113 |
[ |
597 | 114 |
[s atEnd not and:[s position < methodSourcePosition]] whileTrue:[ |
580
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
115 |
s nextLine |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
116 |
]. |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
117 |
lineNumberOfMethod := s lineNumber. |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
118 |
] ensure:[ |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
119 |
s close. |
500 | 120 |
]. |
597 | 121 |
]. |
500 | 122 |
] |
123 |
] |
|
124 |
]. |
|
125 |
]. |
|
126 |
||
127 |
"/ output something (will not generate a ref to the source file) |
|
580
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
128 |
con printReceiverOn:aStream. |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
129 |
aStream nextPutAll:' >> '. |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
130 |
con selector printOn:aStream. |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
131 |
aStream nextPutAll:' ['. |
597 | 132 |
con lineNumber printOn:aStream. |
580
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
133 |
aStream nextPut:$]. |
500 | 134 |
|
526 | 135 |
relPath notNil ifTrue:[ |
500 | 136 |
lineNumberOfMethod notNil ifTrue:[ |
137 |
lineNumberInFile := lineNumberOfMethod + con lineNumber - 1. |
|
138 |
aStream nextPutAll:(' (%1:%2)' |
|
526 | 139 |
bindWith: relPath |
500 | 140 |
with: lineNumberInFile) |
141 |
] ifFalse:[ |
|
142 |
aStream nextPutAll:(' (%1)' |
|
526 | 143 |
bindWith: relPath) |
500 | 144 |
]. |
145 |
]. |
|
146 |
aStream cr. |
|
147 |
||
148 |
"Modified: / 05-08-2012 / 12:00:00 / cg" |
|
580
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
149 |
"Modified: / 12-11-2013 / 23:09:07 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
500 | 150 |
! |
151 |
||
345 | 152 |
rememberEndTime |
479 | 153 |
"remembers the endTime of the current test (in outcome)" |
345 | 154 |
|
155 |
^outcome endTime: Timestamp now |
|
156 |
||
157 |
"Created: / 16-08-2011 / 17:36:07 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
158 |
! |
|
159 |
||
505 | 160 |
rememberException:ex |
345 | 161 |
"common for failure and error: |
162 |
called when a test fails. testCase is the failed |
|
505 | 163 |
testcase, ex is platform specific object describing |
345 | 164 |
the failure. Actually, on all platforms exeptt GemStone, |
505 | 165 |
ex is an instance of an exception that caused the failure" |
345 | 166 |
|
167 |
|backtrace| |
|
168 |
||
169 |
((Smalltalk respondsTo:#isSmalltalkX) and:[Smalltalk isSmalltalkX]) ifTrue:[ |
|
170 |
"remember the backtrace (as string, to prevent objects from being kept forwever |
|
171 |
from being garbage collected, the signal (i.e. the exception class) and the |
|
172 |
exceptions message (description). |
|
173 |
Would like to have an exceptionInfo obejct for that, but that might be hard to |
|
174 |
get returned back into the main stream sunit package..." |
|
175 |
||
176 |
backtrace := String streamContents:[:s | |
|
177 |
|con topReached| |
|
178 |
||
179 |
"could use printAllOn:s, but noone is interested in contexts above the |
|
180 |
testcase's runtest context" |
|
181 |
topReached := false. |
|
505 | 182 |
con := ex suspendedContext. |
345 | 183 |
[ |
184 |
con notNil and:[topReached not] |
|
185 |
] whileTrue:[ |
|
500 | 186 |
self printLineForContextForJavaCompatibleStackTrace:con on:s. |
597 | 187 |
topReached := ((con selector == outcome selector) or:[con selector == #runCase]) |
465 | 188 |
and:[con receiver == outcome |
189 |
or:[ con receiver == outcome testCase ]]. |
|
345 | 190 |
con := con sender. |
191 |
] |
|
192 |
]. |
|
465 | 193 |
|
345 | 194 |
outcome exceptionDetail:(Dictionary new |
571
d5a1ac6d1743
use #creator instead of #signal
Claus Gittinger <cg@exept.de>
parents:
526
diff
changeset
|
195 |
at:#exception put:ex creator; |
505 | 196 |
at:#description put:ex description; |
345 | 197 |
at:#backtrace put:backtrace; |
198 |
yourself). |
|
199 |
^ self. |
|
200 |
]. |
|
201 |
||
202 |
"add other dialect specifics here" |
|
203 |
||
204 |
"Created: / 06-08-2011 / 11:29:23 / cg" |
|
205 |
"Created: / 16-08-2011 / 17:32:36 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
206 |
! |
|
207 |
||
208 |
rememberOutput: aString |
|
209 |
outcome collectedOutput: aString |
|
210 |
||
211 |
"Created: / 16-08-2011 / 18:18:41 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
212 |
! |
|
213 |
||
214 |
rememberStartTime |
|
479 | 215 |
"remembers the startTime of the current test (in outcome)" |
345 | 216 |
|
217 |
^outcome startTime: Timestamp now |
|
218 |
||
219 |
"Created: / 16-08-2011 / 17:36:16 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
220 |
! ! |
|
221 |
||
222 |
!TestResultStX methodsFor:'running'! |
|
223 |
||
224 |
performCase: aTestCase |
|
580
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
225 |
"while performing a testcase, any output to the Transcript is also |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
226 |
collected and is attached to the test result. Nice when tests are executed |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
227 |
automatically, for example by jenkins. |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
228 |
Q: I think, we MUST lock this, |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
229 |
or better: aquire the lock and making collecting explicit via |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
230 |
call to 'self collectingTranscriptOutputDo:[...]' in the testcase. |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
231 |
Otherwise we'll run into trouble, when executing multiple tests in parallel. |
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
232 |
" |
345 | 233 |
|
608 | 234 |
|savedStdout savedTranscript collector| |
345 | 235 |
|
236 |
savedStdout := Stdout. |
|
237 |
savedTranscript := Transcript. |
|
608 | 238 |
collector := CharacterWriteStream new:100. |
345 | 239 |
[ |
240 |
Stdout := SplittingWriteStream on:collector and: Stdout. |
|
241 |
Transcript := SplittingWriteStream on:collector and: Transcript. |
|
242 |
super performCase: aTestCase. |
|
243 |
] ensure:[ |
|
244 |
Stdout := savedStdout. |
|
245 |
Transcript := savedTranscript. |
|
246 |
self rememberOutput: collector contents. |
|
247 |
]. |
|
248 |
||
249 |
"Created: / 16-08-2011 / 18:18:41 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
580
d86ef51e98ab
Fix in TestResultStX>>#printLineForContextForJavaCompatibleStackTrace:on:
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
571
diff
changeset
|
250 |
"Modified (comment): / 29-08-2013 / 11:15:36 / cg" |
345 | 251 |
! ! |
252 |
||
253 |
!TestResultStX class methodsFor:'documentation'! |
|
254 |
||
255 |
version |
|
608 | 256 |
^ '$Header: /cvs/stx/stx/goodies/sunit/TestResultStX.st,v 1.17 2015-04-22 18:04:02 stefan Exp $' |
345 | 257 |
! |
258 |
||
259 |
version_CVS |
|
608 | 260 |
^ '$Header: /cvs/stx/stx/goodies/sunit/TestResultStX.st,v 1.17 2015-04-22 18:04:02 stefan Exp $' |
345 | 261 |
! ! |
571
d5a1ac6d1743
use #creator instead of #signal
Claus Gittinger <cg@exept.de>
parents:
526
diff
changeset
|
262 |