Yua3U‖SFUnitTests.UnitTest service

iRNwD‖The UnitTest service provides a framework for automating unit tests using the Basic language, including the ability to:

note

UEt5G‖Both the unit tests and the code to be tested must be written in Basic. The code being tested may call functions written in other languages.


warning

CCgbB‖The UnitTest service is not available for Python scripts.


PBJpL‖Definitions

kTZBz‖Test Case

2SE2W‖A test case is the individual unit of testing. It checks for a specific response to a particular set of inputs.

XiXCu‖In the UnitTest service, a test case is represented by a single Basic Sub whose name starts with a common prefix (the default is "Test_").

2g5tx‖The test case fails if one of the AssertX methods returns False.

6yQXs‖Test Suite

Jk79j‖A test suite is a collection of test cases that should be executed together.

cFV9D‖All test cases of a test suite are stored in a single Basic module.

UEVyk‖A test suite may implement the SetUp and TearDown methods to prepare for test cases in its module.

nEFMy‖Unit Test

xieZW‖A full unit test consists of a set of test suites in the same Basic library.

6XiCa‖Service invocation

FVzhB‖Before using the UnitTest service the ScriptForge library needs to be loaded or imported:

note

gF8D8‖• Basic macros require to load ScriptForge library using the following statement:
GlobalScope.BasicLibraries.loadLibrary("ScriptForge")

• Python scripts require an import from scriptforge module:
from scriptforge import CreateScriptService


GHXzG‖Simple mode

C5qBi‖Invoke the service in simple mode to call AssertX functions without having to build the full hierarchy of test suites and test cases.

DRzjW‖In simple mode, the service is invoked inside the test case, as shown in the example below:


    Sub SimpleTest
        On Local Error GoTo CatchError
        Dim myTest As Variant
        myTest = CreateScriptService("UnitTest")
    6AMLD‖    ' A few dummy tests
        myTest.AssertEqual(1 + 1, 2)
        myTest.AssertEqual(1 - 1, 0)
    fr8wA‖    MsgBox("All tests passed")
        Exit Sub
    CatchError:
    BCLKL‖    myTest.ReportError("A test failed")
    End Sub
  

ki4xc‖In this example, if any of the AssertEqual calls fail, the interpreter will go to the CatchError label and report the error by calling the ReportError method.

AMsHe‖Full mode

Cev96‖When invoked in full mode, the service creation is external to the test code and all tests are organized into test cases and test suites inside a single library.

kRFxC‖The following example creates a UnitTest instance whose tests are located inside the current document (ThisComponent) in the "Tests" library.


    GlobalScope.BasicLibraries.loadLibrary("ScriptForge")
    Dim myUnitTest As Variant
    myUnitTest = CreateScriptService("UnitTest", ThisComponent, "Tests")
  

3pPFr‖A minimalist example in full mode

ktFcg‖Consider that a ODS file has a module named "MathUtils" in its "Standard" library with the following code:


    ZijqG‖' Code in module Standard.MathUtils
    Function Sum(a, b) As Double
        Sum = a + b
    End Function
    
    Function Multiply(a, b) As Double
        Multiply = a * b
    End Function
  

N8ifA‖To create a full test suite, consider that a new library named "Tests" is created in the file with a single module "AllTests" containing the code below:


    TdD5n‖' Code in module Tests.AllTests
    Sub Main()
        GlobalScope.BasicLibraries.loadLibrary("ScriptForge")
        Dim test As Variant
        test = CreateScriptService("UnitTest", ThisComponent, "Tests")
        test.RunTest("AllTests")
        test.Dispose()
    End Sub
    
    Sub Setup(test)
    EVip5‖    ' Preparation code ran prior to the first test case
        Dim exc As Variant
        exc = CreateScriptService("Exception")
        exc.Console(Modal := False)
    End Sub
    
    Sub TearDown(test)
    VwiNK‖    ' Optional cleanup code called after the last test case
    End Sub
    
    Sub Test_Sum(test)
        On Local Error GoTo CatchError
    km3se‖    test.AssertEqual(Sum(1, 1), 2, "Sum two positive integers")
    nFKE8‖    test.AssertEqual(Sum(-10, 20), 10, "Sum of negative and positive integers")
    pmhLE‖    test.AssertEqual(Sum(1.5, 1), 2.5, "Sum of float and integer values")
        Exit Sub
    CatchError:
    kf7KV‖    test.ReportError("Sum method is broken")
    End Sub
    
    Sub Test_Multiply(test)
        On Local Error GoTo CatchError
    kf6AB‖    test.AssertEqual(Multiply(2, 2), 4, "Multiply two positive integers")
    fWRh4‖    test.AssertEqual(Multiply(-4, 2), -8, "Multiply negative and positive integers")
    7wxBD‖    test.AssertEqual(Multiply(1.5, 3), 4.5, "Multiply of float and integer values")
        Exit Sub
    CatchError:
    fEEkx‖    test.ReportError("Multiply method is broken")
    End Sub
  

y6q9H‖The test suite above consists of two test cases Test_Sum and Test_Multiply. To run all tests simply run the Main method from the "AllTests" module.

mGjTt‖The Console from the Exception service is used as the default output to print test results. After running the example above, the following output will be displayed in the console:


    ' RUNTEST ENTER testsuite='Tests.AllTests', pattern='Test_*'
    '   SETUP Tests.AllTests.Setup() ENTER
    '   SETUP Tests.AllTests.Setup() EXIT
    '   TESTCASE Tests.AllTests.Test_Multiply() ENTER
    '   TESTCASE Tests.AllTests.Test_Multiply() EXIT (0,017 sec)
    '   TESTCASE Tests.AllTests.Test_Sum() ENTER
    '   TESTCASE Tests.AllTests.Test_Sum() EXIT (0,016 sec)
    '   TEARDOWN Tests.AllTests.TearDown() ENTER
    '   TEARDOWN Tests.AllTests.TearDown() EXIT
    ' RUNTEST EXIT testsuite='Tests.AllTests' (0,223 sec)
  

SX4Hy‖If any of the AssertEqual methods fails during these tests, an error message is added to the console.

SKsNp‖Properties

dUKA3‖Name

4CFLw‖Readonly

hmcQA‖Type

qr48K‖Description

LongMessage

BLCXX‖No

Boolean

LwYBg‖When set to True (default) the console shows the standard message appended to the message provided by the tester. When False, only the message defined by the tester is used.

ReturnCode

m6reQ‖Yes

Integer

diGQ4‖Value returned by RunTest after the unit test is finished. Next is a list of possible values:

RqYbB‖0 - Test finished without errors or test not started
1 - An assertion within a test case returned False
2 - A SkipTest was issued by the Setup method or by one of the test cases.
3 - Abnormal end of test

Verbose

sa2t9‖No

Boolean

WG8MM‖When set to True, all assertions are reported in the console (failing or not). When False (default), only failing assertions are reported.

WhenAssertionFails

kbkBT‖No

Integer

H5D7L‖Defines what is done when an assertion fails. Next is a list of possible values:

EQBpN‖0 - Ignore the failure and continue running the test
1 - The TearDown method in the module is executed in the current test suite and the next suite is started (default in full mode).
2 - Stop immediately (default in simple mode)


oxRCB‖List of Methods in the UnitTest Service

AssertAlmostEqual
AssertEqual
AssertFalse
AssertGreater
AssertGreaterEqual
AssertIn
AssertIsInstance
AssertIsNothing
AssertLike

AssertNotRegex
AssertIsNull
AssertLess
AssertLessEqual
AssertNotAlmostEqual
AssertNotEqual
AssertNotIn
AssertNotInstance
AssertNotLike

AssertNotNothing
AssertNotNull
AssertRegex
AssertTrue
Fail
Log
ReportError
RunTest
SkipTest


d4CFS‖Arguments of the AssertX methods

ArRiA‖All assertions test one or two expressions, referred in the remainder of this help page as A and B. They are always the first one or two arguments in the AssertX method.

Nanrc‖All AssertX methods accept a message argument specifying a custom message to be reported in the console regarding the assertion. By default an empty string is used. This argument is always in the last position of the assertion.

d7AFB‖Some AssertX methods also accept additional arguments, as described by their syntaxes below.

AssertAlmostEqual

xbDmc‖Returns True when A and B are numerical values and are considered to be close to each other, given a relative tolerance.

FVEx2‖Syntax:

svc.AssertAlmostEqual(a: any, b: any, tolerance: double = 1E-09, message: str = ""): bool

STVnD‖This assertion returns True if the two conditions below are met:

AssertEqual

Z7Aap‖Returns True when A and B are considered to be equal.

FVEx2‖Syntax:

svc.AssertEqual(a: any, b: any, message: str = ""): bool

5EHVv‖When A and B are scalars, True is returned if:

WpMkU‖When A and B are arrays, True is returned if:

AssertFalse

PxfTp‖Returns True when the type of A is Boolean and its value is False.

FVEx2‖Syntax:

svc.AssertFalse(a: any, message: str = ""): bool

AssertGreater

C3NgG‖Returns True when A is greater than B.

FVEx2‖Syntax:

svc.AssertGreater(a: any, b: any, message: str = ""): bool

bT3CG‖The comparison between A and B assumes the following:

AssertGreaterEqual

HtcFS‖Returns True when A is greater than or equal to B.

FVEx2‖Syntax:

svc.AssertGreaterEqual(a: any, b: any, message: str = ""): bool

gwLLH‖The comparison between A and B assumes the following:

AssertIn

BcYoQ‖Returns True when A is found in B.

FVEx2‖Syntax:

svc.AssertIn(a: any, b: any, message: str = ""): bool

UqzzY‖This assertion assumes the following:

AssertIsInstance

pCSa8‖Returns True when A is an instance of a specified object type, specified as a string containing the type name.

FVEx2‖Syntax:

svc.AssertIsInstance(a: any, objecttype: str, message: str = ""): bool

P4Q7u‖Expression A may be one of the following:

AssertIsNothing

cNXhg‖Returns True when A is an object that has the Nothing value.

FVEx2‖Syntax:

svc.AssertIsNothing(a: any, message: str = ""): bool

AssertIsNull

DAqbe‖Returns True when A has the Null value.

FVEx2‖Syntax:

svc.AssertIsNull(a: any, message: str = ""): bool

AssertLess

oQpZL‖Returns True when A is less than B.

FVEx2‖Syntax:

svc.AssertLess(a: any, b: any, message: str = ""): bool

DGdwP‖The comparison between A and B assumes the following:

AssertLessEqual

wAvBZ‖Returns True when A is less than or equal to B.

FVEx2‖Syntax:

svc.AssertLessEqual(a: any, b: any, message: str = ""): bool

kvCHD‖The comparison between A and B assumes the following:

AssertLike

Zg5MZ‖Returns True if string A matches a given pattern containing wildcards.

FVEx2‖Syntax:

svc.AssertLike(a: any, pattern: str = "", message: str = ""): bool

GD2Hu‖The following wildcards are accepted:

AssertNotAlmostEqual

fsu2Z‖Returns True when A and B are numerical values and are not considered to be close to each other, given a relative tolerance.

FVEx2‖Syntax:

svc.AssertNotAlmostEqual(a: any, b: any, tolerance: double = 1E-09, message: str = ""): bool

3CNkz‖This assertion returns True if the two conditions below are met:

AssertNotEqual

KVBYJ‖Returns True when A and B are not considered to be equal.

FVEx2‖Syntax:

svc.AssertNotEqual(a: any, b: any, message: str = ""): bool

AyCxD‖This method works both for scalars and arrays. Read the instructions in AssertEqual for more information on what equality means in this assertion.

AssertNotIn

ENDBA‖Returns True when A (a string) is not found in B.

FVEx2‖Syntax:

svc.AssertNotIn(a: any, b: any, message: str = ""): bool

iGakQ‖Read the instructions in AssertIn for more information on the assumptions of this method.

AssertNotInstance

BCzDu‖Returns True when A is not an instance of a specified object type.

FVEx2‖Syntax:

svc.AssertNotInstance(a: any, objecttype: str, message: str = ""): bool

oa8bz‖Read the instructions in AssertIsInstance for more information on the assumptions of this method.

AssertNotLike

TRtFA‖Returns True if string A does not match a given pattern containing wildcards.

FVEx2‖Syntax:

svc.AssertNotLike(a: any, pattern: str = "", message: str = ""): bool

2ubh9‖Read the instructions in AssertLike for more information on the assumptions of this method.

AssertNotNothing

C9GJn‖Returns True except when A is an object that has the Nothing value.

FVEx2‖Syntax:

svc.AssertNotNothing(a: any, message: str = ""): bool

AssertNotNull

tdWWt‖Returns True except when A has the Null value.

FVEx2‖Syntax:

svc.AssertNotNull(a: any, message: str = ""): bool

AssertNotRegex

piNCq‖Returns True when A is not a string or does not match the given regular expression.

FVEx2‖Syntax:

svc.AssertNotRegex(a: any, regex: str = "", message: str = ""): bool

24iRs‖The comparison is case-sensitive.

AssertRegex

LBAZt‖Returns True when string A matches the given regular expression.

FVEx2‖Syntax:

svc.AssertRegex(a: any, regex: str = "", message: str = ""): bool

YDnGG‖The comparison is case-sensitive.

AssertTrue

B2c4q‖Returns True when expression A is a Boolean and its value is True.

FVEx2‖Syntax:

svc.AssertTrue(a: any, message: str = ""): bool

Fail

CsZXs‖Forces a test case to fail.

FVEx2‖Syntax:

svc.Fail(message: str = "")

aMzvc‖A message can be provided to be reported in the console.

Log

6ZD5u‖Writes the specified message in the console.

FVEx2‖Syntax:

svc.Log(message: str = "")

HmfG2‖A message can be provided to be reported in the console.

ReportError

b2AUv‖Displays a message box with a message and the current property values of the Exception service.

by77W‖This method is commonly used in the exception handling section of the Sub containing the test case, which is reached when an assertion fails or when the Fail method is called.

FVEx2‖Syntax:

svc.ReportError(message: str = "")

ozRN8‖Depending on the value of the property WhenAssertionFails, the test execution may continue or be interrupted.

q42xs‖When writing test cases it is recommended to include a call to the ReportError method in the exception handling section of the Sub.

pze6V‖If the property LongMessage is equal to True, the specified message is followed by the standard error message description. Otherwise only the message is displayed.

RunTest

AtCyJ‖Executes the complete test suite implemented in the specified module. Each test case is run independently from each other.

AqkBH‖Running a test suite consists of:

  1. YqC5U‖Executing the optional Setup method present in the module.

  2. Kmshw‖Executing once each test case, in no specific order.

  3. dpWzo‖Executing the optional TearDown method present in the module.

FVEx2‖Syntax:

svc.RunTest(testsuite: str, testcasepattern: str = "", message: str = ""): int

rFf8d‖The argument testcasepattern specifies a pattern composed of "?" and "*" wildcards to select which test cases will be run. The comparison is not case-sensitive.

T3faF‖If a message is provided, it is written to the console when the test starts.

SkipTest

TDXg5‖Interrupts the running test suite without calling the TearDown method.

A6W9G‖Skipping a test is usually meaningful during the Setup method when not all conditions to run the test are met.

wzZy2‖It is up to the Setup method to exit the Sub shortly after the SkipTest call.

KEaV4‖If SkipTest is called from within a test case, the execution of the test suite is interrupted and the remaining test cases are not run. Keep in mind that the order in which test cases are run is arbitrary within a test suite.

FVEx2‖Syntax:

svc.SkipTest(message: str = "")

BFyev‖If a message is provided, it is written to the console.