gambas-source-code/main/lib/test/gb.test/.src/TestSuite/Assert.module
Tobias Boege 62823aed08 gb.test: Improve diagnostics of Approximate assertions
[GB.TEST]
* BUG: Improve diagnostics of Approximate and RelativeApproximate assertions, showing the original values too.
2020-08-09 22:11:07 +02:00

309 lines
8.4 KiB
Text

' Gambas module file
''' This module extends the Assert instruction, which checks
''' that Expression is TRUE, and if the Expression is FALSE,
''' an uncatchable "Assertion failed" error is raised, the
''' PRINT or ERROR instruction is executed, and the program stops immediately.
Export
Public _IntendedFailure As Boolean
'' Assert that Result = True
Public Sub Ok(Result As Boolean, Optional Description As String) As Boolean
Dim bRes As Boolean
If Test._InSetup = True Then
Test.BailOut(("Failure: Assertion forbidden inside _Setup or _Teardown."))
Endif
If _IntendedFailure Then Result = Not Result
_IntendedFailure = False
DAWAI:
Test._Next.Ok = Result
Test._Next.Description = Description
bRes = Test._Printer.Assert(Test._Next).Ok
Test._Next = New TestAssertion
Return bRes
End
' -------------------- High-level test functions --------------------
'' Assert that a test is passed. Reports Ok
Public Sub Pass(Optional Description As String) As Boolean
Return Ok(True, Description)
End
'' Assert fail. Reports not ok.
Public Sub Fail(Optional Description As String) As Boolean
Return Ok(False, Description)
End
'' Assert that Result = False.
Public Sub NotOk(Result As Boolean, Optional Description As String) As Boolean
Return Ok(Not Result, Description)
End
'' Assert that Got = Expected
Public Sub Equals(Got As Variant, Expected As Variant, Optional Description As String) As Boolean
Dim bRes As Boolean
bRes = Ok(Got = Expected, Description)
If Not bRes Then
NoteGotAndExpected(Got, Expected)
Endif
Return bRes
End
'' Assert that Got <> Expected
Public Sub Notequals(Got As Variant, UnExpected As Variant, Optional Description As String) As Boolean
Return Ok(Got <> UnExpected, Description)
End
'' Assert that Got <= Bound
Public Sub LessEqual(Got As Variant, Bound As Variant, Optional Description As String) As Boolean
Dim bRes As Boolean
bRes = Ok(Got <= Bound, Description)
If Not bRes Then
NoteGotAndExpected(Got, Bound)
Endif
Return bRes
End
'' Assert that Got < Bound
Public Sub Less(Got As Variant, Bound As Variant, Optional Description As String) As Boolean
Dim bRes As Boolean
bRes = Ok(Got < Bound, Description)
If Not bRes Then
NoteGotAndExpected(Got, Bound)
Endif
Return bRes
End
'' Assert that Got >= Bound
Public Sub GreaterEqual(Got As Variant, Bound As Variant, Optional Description As String) As Boolean
Dim bRes As Boolean
bRes = Ok(Got >= Bound, Description)
If Not bRes Then
NoteGotAndExpected(Got, Bound)
Endif
Return bRes
End
'' Assert that Got > Bound
Public Sub Greater(Got As Variant, Bound As Variant, Optional Description As String) As Boolean
Dim bRes As Boolean
bRes = Ok(Got > Bound, Description)
If Not bRes Then
NoteGotAndExpected(Got, Bound)
Endif
Return bRes
End
'' Asserts that _Got_ has an [absolute error](https://en.wikipedia.org/wiki/Approximation_error) to _Expected_ of at most _Precision_.
Public Sub Approximate(Got As Float, Expected As Float, Precision As Float, Optional Description As String) As Boolean
Dim bRes As Boolean
Dim fAbsError As Float
fAbsError = Abs(Got - Expected)
bRes = Ok(fAbsError <= Precision, Description)
If Not bRes Then
Test.Note(Null)
Test.Note(Subst$(("------------- Expected -------------" & gb.lf & "AbsError(&1, &2) <= &3"), Got, Expected, Precision))
Test.Note(Null)
Test.Note(Subst$(("---------------- Got ---------------" & gb.lf & "Got = &1" & gb.lf & "Expected = &2" & gb.lf & "|Got - Expected| = &3"), Got, Expected, fAbsError))
Test.Note("------------------------------------")
Test.Note(Null)
Endif
Return bRes
End
'' Asserts that _Got_ has a [relative error](https://en.wikipedia.org/wiki/Approximation_error) to _Expected_ of at most _RelPrecision_.
'' _Expected_ may not be zero, unless _Got_ is also zero in which case the test succeeds.
Public Sub RelativeApproximate(Got As Float, Expected As Float, RelPrecision As Float, Optional Description As String) As Boolean
Dim bRes As Boolean
Dim fRelError As Float
If Abs(Expected) = 0.0 Then
bRes = Ok(Abs(Got) = 0.0, Description)
Test.Note(("Expected value in RelativeApproximate is 0.0. Comparing value with 0.0 exactly..."))
Return bRes
Endif
fRelError = Abs((Got - Expected) / Expected)
bRes = Ok(fRelError <= RelPrecision)
If Not bRes Then
Test.Note(Null)
Test.Note(Subst$(("------------- Expected -------------" & gb.lf & "RelError(&1, &2) <= &3"), Got, Expected, RelPrecision))
Test.Note(Null)
Test.Note(Subst$(("---------------- Got ---------------" & gb.lf & "Got = &1" & gb.lf & "Expected = &2" & gb.lf & "|Got - Expected|/|Expected| = &3"), Got, Expected, fRelError))
Test.Note("------------------------------------")
Test.Note(Null)
Endif
Return bRes
End
'' Assert that Got is of the type Type
Public Sub IsType(Got As Variant, Type As Integer, Optional Description As String) As Boolean
Return Equals(TypeOf(Got), Type, Description)
End
'' Assert that Got = Null
Public Sub Null(Got As Variant, Optional Description As String) As Boolean
Return Equals(Got, Null, Description)
End
'' Assert that Got <> Null
Public Sub NotNull(Got As Variant, Optional Description As String) As Boolean
Return Notequals(Got, Null, Description)
End
'' Assert that Got Like Pattern. See also the Like string operator.
Public Sub Like(Got As String, Pattern As String, Optional Description As String) As Boolean
Dim bRes As Boolean
bRes = Ok(Got Like Pattern, Description)
If Not bRes Then
NoteGotAndExpected(Got, Pattern)
Endif
Return bRes
End
'' Assert that Got Match Pattern. See also the Match string operator.
Public Sub Match(Got As String, Pattern As String, Optional Description As String) As Boolean
Dim bRes As Boolean
bRes = Ok(Got Match Pattern, Description)
If Not bRes Then
NoteGotAndExpected(Got, Pattern)
Endif
Return bRes
End
'' Assert that Got = Expected. On failure reports hints about the difference.
Public Sub StringEquals(Got As String, Expected As String, Optional Description As String) As Boolean
Dim bRes As Boolean
Dim iPos As Integer
bRes = Equals(Got, Expected, Description)
If Not bRes Then
If Len(Got) <> Len(Expected) Then
Test.Note(Subst$(("Strings are of different lengths &1 and &2, respectively."), Len(Got), Len(Expected)))
Endif
For iPos = 1 To Min(Len(Got), Len(Expected))
If Mid$(Got, iPos, 1) <> Mid$(Expected, iPos, 1) Then Break
Next
Test.Note(Subst$(("Strings differ at position &1."), iPos))
Endif
Return bRes
End
'' Assert that an error happened. Reports not ok if no error happened.
''
'' Example:
'' Try 2/0
'' Assert.Error("division by zero")
Public Sub Error(Optional Description As String) As Boolean
Return Ok( Error , Description)
End
'' Assert that an error happened with error code. Reports not ok
'' if no error happend or if the error code is wrong.
''
'' Example:
'' Try Print 2 / 0
'' Assert.ErrorCode(26, "division by zero with code 26")
Public Sub ErrorCode(Code As Integer, Optional Description As String) As Boolean
Dim bRes As Boolean
If Not Error Then
bRes = Fail(Description)
Test.Note(("No error happened"))
Else
bRes = Equals(Error.Code, Code, Description)
If Not bRes Then
Test.Note(Subst$(("Error was: &1 (code: &2) at &3"), Error.Text, Error.Code, Error.Where))
Endif
Endif
Error.Clear()
Return bRes
End
'' Assert that no error happened.
''
''Example:
''
''Try Print 2 / 2
''Assert.Noterror("Division ok")
Public Sub Noterror(Optional Description As String) As Boolean
Dim bRes As Boolean
bRes = Ok(Not Error , Description)
If Not bRes Then
Test.Note(Subst$(("Error was: &1 (code: &2) at &3"), Error.Text, Error.Code, Error.Where))
Endif
Error.Clear()
Return bRes
End
' ------------------------------------------------- Helper functions
Private Sub NoteGotAndExpected(Got As String, Expected As String)
Test.Note(Null)
Test.Note(Subst$(("------------- Expected -------------" & gb.lf & "&1"), Expected))
Test.Note(Null)
Test.Note(Subst$(("---------------- Got ---------------" & gb.lf & "&1"), Got))
Test.Note("------------------------------------")
Test.Note(Null)
End