gambas-source-code/comp/src/gb.test/.src/TestSuite/Test.module

270 lines
7.3 KiB
Text
Raw Normal View History

' Gambas module file
Export
Property Read Printer As TapPrinter
Property Output As Stream
Property Read Session As TapContext
Property Read Finished As Boolean
Property _Next As TestAssertion
Private $hPrinter As New TapPrinter
Private $hNext As TestAssertion
2020-04-07 16:48:46 +02:00
''' The static procedure Test.Main() starts test(s).
'' Runs all tests in all testcontainers and prints the result to the console.
2020-04-07 16:48:46 +02:00
'' With Test.Main(NameTestModule) the tests can be restricted to only those of a single test module.
'' With Test.Main(NameTestModule, NameProcedure) only a single test can be accomplished.
Public Sub Main(Optional Tests As String)
Test.Reset() ' only if you run this Main multiple times per process, which you shouldn't
RunTests(Tests)
PrintSummary()
End
Private Sub PrintSummary()
'needed for debugging, to doubleclick on it
Dim Session As TapContext
Session = Test.Session
With Session
Test.Print(gb.Lf) ' better readability for humans
Test.Note(Subst$(("&2 - ran: '&1' "), .Summary.Description, IIf(.Summary.Success, "PASSED", "FAILED")))
If .TestsRun <> .Plan Then Test.Note(Subst$(("Planned &1 tests but ran &2"), .Plan, .TestsRun))
Test.Note(gb.Lf)
If Not .Summary.Success Then ShowTestCollection(("&1 tests failed:"), FindFailures(.Summary.Subtests, ""))
ShowTestCollection(("&1 tests skipped:"), FindSkips(.Summary.Subtests, ""))
ShowTestCollection(("&1 tests todo:"), FindTodos(.Summary.Subtests, ""))
ShowTestCollection(("&1 tests bonus:"), FindBonus(.Summary.Subtests, ""))
End With
End
'' Prints a Collection[] of tests as returned by FindFailures, FindSkips, FindTodos.
'' _Description_ can contain '&1' which is substituted for _TestCollection_.Count.
Private Sub ShowTestCollection(Description As String, TestCollection As Collection[])
Dim cTest As Collection
If TestCollection.Count Then
Test.Note(Subst$(Description, TestCollection.Count))
For Each cTest In TestCollection
Dim hTest As TestAssertion = cTest!Assertion
Test.Note(Subst$(("&2: &1 -- &3 &4"), cTest["Path"], hTest.Id, hTest.Description, IIf(hTest.Comment, "# " & hTest.Comment, "")))
Next
Test.Note(gb.Lf)
Endif
End
Private Function FindFailures(Tests As TestAssertion[], Prefix As String) As Collection[]
Dim hTest As TestAssertion
Dim sName As String
Dim aRet As New Collection[]
For Each hTest In Tests
sName = Prefix &/ hTest.Description
' Only show the deepest subtests that caused failures.
If Not hTest.Success And If Not hTest.Subtests.Count Then aRet.Add(["Path": Prefix, "Assertion": hTest])
aRet.Insert(FindFailures(hTest.Subtests, sName))
Next
Return aRet
End
Private Function FindSkips(Tests As TestAssertion[], Prefix As String) As Collection[]
Dim hTest As TestAssertion
Dim sName As String
Dim aRet As New Collection[]
For Each hTest In Tests
sName = Prefix &/ hTest.Description
If hTest.Directive = Tap.SKIP Then aRet.Add(["Path": Prefix, "Assertion": hTest])
aRet.Insert(FindSkips(hTest.Subtests, sName))
Next
Return aRet
End
Private Function FindTodos(Tests As TestAssertion[], Prefix As String) As Collection[]
Dim hTest As TestAssertion
Dim sName As String
Dim aRet As New Collection[]
For Each hTest In Tests
sName = Prefix &/ hTest.Description
If hTest.Directive = Tap.TODO And If Not hTest.Ok Then aRet.Add(["Path": Prefix, "Assertion": hTest])
aRet.Insert(FindTodos(hTest.Subtests, sName))
Next
Return aRet
End
Private Function FindBonus(Tests As TestAssertion[], Prefix As String) As Collection[]
Dim hTest As TestAssertion
Dim sName As String
Dim aRet As New Collection[]
For Each hTest In Tests
sName = Prefix &/ hTest.Description
If hTest.Directive = Tap.TODO And If hTest.Ok Then aRet.Add(["Path": Prefix, "Assertion": hTest])
aRet.Insert(FindBonus(hTest.Subtests, sName))
Next
Return aRet
End
'' Run all tests, optional limited by Container or TestCaseName. Track contains .
Private Function RunTests(Tests As String)
Dim aTestCommands As TestCommand[]
Dim sTestModule As String
Dim TestModule As Class
Dim Suite As New TestSuite
aTestCommands = TestCommand.ParseCommands(Tests)
For Each sTestModule In GetAllTestModules(aTestCommands)
TestModule = Class.Load(sTestModule)
Suite.AddAllTestCases(TestModule, aTestCommands)
Next
Test.Session.Summary.Description = Tests
Suite.Run()
If Not Test.Finished Then Test.Finish()
End
Function GetAllTestModules(Commands As TestCommand[]) As String[]
Dim TestClass As Class
Dim TestModuleNames As New String[]
Dim sNames As New String[]
Dim sName As String
Dim Command As TestCommand
If Exist(".../.test")
sNames = Split(File.Load(".../.test"), gb.Lf, Null, True)
Endif
Assert sNames
sNames.Sort
For Each sName In sNames
TestClass = Class.Load(sName)
If Not TestClass Then Error.Raise(Subst$(("Could not load test module '&1'"), sName))
If TestModuleNames.Exist(sName) Then Continue
If Commands.Count = 0 Then
'Add every Testmodule
TestModuleNames.Add(sName)
Else
'Add only testmodules whose names exist in Commands
For Each Command In Commands
If Not sNames.Exist(Command.ModuleName) Then
Test.BailOut(Subst$(("There is no test called &1."), Command.ModuleName))
Endif
If Lower(Command.ModuleName) = Lower(sName) Then
TestModuleNames.Add(sName)
Endif
Next
Endif
Next
TestModuleNames.Sort
Return TestModuleNames
Catch
Test.BailOut("Error in " & Error.Where & ": " & Error.Text)
End
' ------------------------------------------------- Test controls
Public Sub BailOut(Optional Comment As String)
$hPrinter.BailOut(Comment)
Quit 1
End
'' Synonym for Note
Public Sub Diagnostic(Comment As String)
$hPrinter.Diagnostic(Comment)
End
'' Synonym for Diagnostic
Public Sub Note(Comment As String)
$hPrinter.Note(Comment)
End
Public Sub Print({Line} As String)
$hPrinter.Print({Line})
End
Private Function Printer_Read() As TapPrinter
Return $hPrinter
End
Private Function Output_Read() As Stream
Return $hPrinter.Output
End
Private Sub Output_Write(Value As Stream)
$hPrinter.Output = Value
End
Private Function Session_Read() As TapContext
Return $hPrinter.Session
End
Private Function Finished_Read() As Boolean
Return $hPrinter.Session.Finished
End
Public Sub Reset()
$hPrinter = New TapPrinter As "Printer"
End
Private Function _Next_Read() As TestAssertion
If $hNext = Null Then
$hNext = New TestAssertion
Endif
Return $hNext
End
Private Sub _Next_Write(Value As TestAssertion)
$hNext = Value
End
Public Sub Subtest(Description As String, Optional Tests As Integer, Optional Comment As String)
Test.Printer.Subtest(Description, Tests, Comment)
End
Public Sub Plan(Tests As Integer, Optional Comment As String)
Test.Printer.Plan(Tests, Comment)
End
Public Sub SkipAll(Optional Comment As String)
Test.Printer.SkipAll(Comment)
End
Public Sub Finish()
Test.Printer.Finish()
End