#FEATURE by cg
class: TestCase
added: #invokeTestMethod
changed: #performTest
support timeout annotation
"{ Package: 'stx:goodies/sunit' }"
"{ NameSpace: Smalltalk }"
TestResult subclass:#TestResultStX
instanceVariableNames:''
classVariableNames:''
poolDictionaries:''
category:'SUnit-Smalltalk/X'
!
!TestResultStX class methodsFor:'utilities'!
sourceFilenameOfClass:aClass
"that is ST/X specific"
"no Smalltalk/X dialect detection needed..."
|sourceStream testClassSourceFile|
sourceStream := aClass sourceStream.
sourceStream notNil ifTrue:[
[
sourceStream := sourceStream stream.
sourceStream isFileStream ifTrue:[
testClassSourceFile := sourceStream pathName asFilename pathName.
].
] ensure:[
sourceStream notNil ifTrue:[ sourceStream close ].
]
].
^ testClassSourceFile
! !
!TestResultStX methodsFor:'accessing'!
endTime
^ endTime
!
endTime:aTimestamp
"sets the overall (suite) end time"
endTime := aTimestamp.
!
executionTime
"return the execution time (in seconds). If asked before or during a run, return nil"
|t1 t2|
(t1 := self startTime) isNil ifTrue:[^ nil].
(t2 := self endTime) isNil ifTrue:[^ nil].
^ t2 secondDeltaFrom: t1
"
|a b|
a := Timestamp now.
Delay waitForMilliseconds:567.
b := Timestamp now.
b - a
"
!
startTime
^ timestamp
!
startTime:aTimestamp
"sets the overall (suite) start time"
timestamp := aTimestamp.
! !
!TestResultStX methodsFor:'outcome'!
printLineForContextForJavaCompatibleStackTrace:con on:aStream
"why in java-backtrace format?
Because then jenkins will be able to extract sourcefile and linenumber
and generate links in the report page.
I am not willing to write another plugin for this - using junit compatible format"
|cls classSourceStream method s lineNumberOfMethod lineNumberInFile relPath methodSourcePosition|
"/ used to be:
"/ con printOn:aStream.
"/ be careful: some tests generate methods on the fly, which are unbound!!
"/ or even (javascript/other languages) may not have a method at all!!!!
con fixAllLineNumbers.
(method := con method) notNil ifTrue:[
cls := method mclass.
cls notNil ifTrue:[
relPath := cls package copyReplaceAll:$: with:$/.
relPath := relPath asUnixFilenameString.
relPath := (relPath asFilename construct:cls theNonMetaclass classFilename) name.
method isJavaMethod ifTrue:[
lineNumberOfMethod := method lineNumberForPC0: 0.
] ifFalse:[
methodSourcePosition := method sourcePosition.
methodSourcePosition notNil ifTrue:[
classSourceStream := cls sourceStream.
classSourceStream notNil ifTrue:[
"/ sigh - we have the lineNumber within the method,
"/ and the characterPosition of the method's start.
"/ need to calculate the absolute lineNumber in the file
s := LineNumberReadStream on:classSourceStream "(classSourceFile asFilename readStream)".
[
[s atEnd not and:[s position < methodSourcePosition]] whileTrue:[
s nextLine
].
lineNumberOfMethod := s lineNumber.
] ensure:[
s close.
].
].
]
]
].
].
"/ output something (will not generate a ref to the source file)
con printReceiverOn:aStream.
aStream nextPutAll:' >> '.
con selector printOn:aStream.
aStream nextPutAll:' ['.
con lineNumber printOn:aStream.
aStream nextPut:$].
relPath notNil ifTrue:[
lineNumberOfMethod notNil ifTrue:[
lineNumberInFile := lineNumberOfMethod + con lineNumber - 1.
aStream nextPutAll:(' (%1:%2)'
bindWith: relPath
with: lineNumberInFile)
] ifFalse:[
aStream nextPutAll:(' (%1)'
bindWith: relPath)
].
].
aStream cr.
"Modified: / 05-08-2012 / 12:00:00 / cg"
"Modified: / 12-11-2013 / 23:09:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
rememberEndTime
"remembers the endTime of the current test (in outcome)"
^outcome endTime: Timestamp now
"Created: / 16-08-2011 / 17:36:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
rememberException:ex
"common for failure and error:
called when a test fails. testCase is the failed
testcase, ex is platform specific object describing
the failure. Actually, on all platforms except GemStone,
ex is an instance of an exception that caused the failure"
|backtrace|
((Smalltalk respondsTo:#isSmalltalkX) and:[Smalltalk isSmalltalkX]) ifTrue:[
"remember the backtrace (as string, to prevent objects from being kept forwever
from being garbage collected, the signal (i.e. the exception class) and the
exceptions message (description).
Would like to have an exceptionInfo obejct for that, but that might be hard to
get returned back into the main stream sunit package..."
backtrace := String streamContents:[:s |
|con topReached|
"could use printAllOn:s, but noone is interested in contexts above the
testcase's runtest context"
topReached := false.
con := ex suspendedContext.
[
con notNil and:[topReached not]
] whileTrue:[
self printLineForContextForJavaCompatibleStackTrace:con on:s.
topReached := ((con selector == outcome selector) or:[con selector == #runCase])
and:[con receiver == outcome
or:[ con receiver == outcome testCase ]].
con := con sender.
]
].
outcome exceptionDetail:(Dictionary new
at:#exception put:ex creator;
at:#description put:ex description;
at:#backtrace put:backtrace;
yourself).
^ self.
].
"add other dialect specifics here"
"Created: / 06-08-2011 / 11:29:23 / cg"
"Created: / 16-08-2011 / 17:32:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (format): / 22-05-2017 / 18:26:41 / mawalch"
!
rememberOutput: aString
outcome collectedOutput: aString
"Created: / 16-08-2011 / 18:18:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
rememberStartTime
"remembers the startTime of the current test (in outcome)"
^outcome startTime: Timestamp now
"Created: / 16-08-2011 / 17:36:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!TestResultStX methodsFor:'running'!
performCase: aTestCase
"while performing a testcase, any output to the Transcript is also
collected and is attached to the test result. Nice when tests are executed
automatically, for example by jenkins.
Q: I think, we MUST lock this,
or better: acquire the lock and making collecting explicit via
call to 'self collectingTranscriptOutputDo:[...]' in the testcase.
Otherwise we'll run into trouble, when executing multiple tests in parallel.
"
|savedStdout savedTranscript collector|
savedStdout := Stdout.
savedTranscript := Transcript.
collector := CharacterWriteStream new:100.
[
Stdout := SplittingWriteStream on:collector and: Stdout.
Transcript := SplittingWriteStream on:collector and: Transcript.
super performCase: aTestCase.
] ensure:[
Stdout := savedStdout.
Transcript := savedTranscript.
self rememberOutput: collector contents.
].
"Created: / 16-08-2011 / 18:18:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (comment): / 29-08-2013 / 11:15:36 / cg"
! !
!TestResultStX class methodsFor:'documentation'!
version
^ '$Header$'
!
version_CVS
^ '$Header$'
! !