Remove duplicated include
[LibreOffice.git] / wizards / source / sfunittests / SF_UnitTest.xba
blobbaeef90de3b38b50d052257f3e43f379bf7e5f1a
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
3 <script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_UnitTest" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
4 REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
5 REM === Full documentation is available on https://help.libreoffice.org/ ===
6 REM =======================================================================================================================
8 Option Compatible
9 Option ClassModule
11 Option Explicit
13 &apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
14 &apos;&apos;&apos; SF_UnitTest
15 &apos;&apos;&apos; ===========
16 &apos;&apos;&apos; Class providing a framework to execute and check sets of unit tests.
17 &apos;&apos;&apos;
18 &apos;&apos;&apos; The UnitTest unit testing framework was originally inspired by unittest.py in Python
19 &apos;&apos;&apos; and has a similar flavor as major unit testing frameworks in other languages.
20 &apos;&apos;&apos;
21 &apos;&apos;&apos; It supports test automation, sharing of setup and shutdown code for tests,
22 &apos;&apos;&apos; aggregation of tests into collections.
23 &apos;&apos;&apos;
24 &apos;&apos;&apos; Both the
25 &apos;&apos;&apos; - code describing the unit tests
26 &apos;&apos;&apos; - code to be tested
27 &apos;&apos;&apos; must be written exclusively in Basic (the code might call functions written in other languages).
28 &apos;&apos;&apos; Even if either code may be contained in the same module, a much better practice is to
29 &apos;&apos;&apos; store them in separate libraries.
30 &apos;&apos;&apos; Typically:
31 &apos;&apos;&apos; - in a same document when the code to be tested is contained in that document
32 &apos;&apos;&apos; - either in a &quot;test&quot; document or in a &quot;My Macros&quot; library when the code
33 &apos;&apos;&apos; to be tested is a shared library (My Macros or LibreOffice Macros).
34 &apos;&apos;&apos; The code to be tested may be released as an extension. It does not need to make
35 &apos;&apos;&apos; use of ScriptForge services in any way.
36 &apos;&apos;&apos;
37 &apos;&apos;&apos; The test reporting device is the Console. Read about the console in the ScriptForge.Exception service.
38 &apos;&apos;&apos;
39 &apos;&apos;&apos; Definitions:
40 &apos;&apos;&apos; - Test Case
41 &apos;&apos;&apos; A test case is the individual unit of testing.
42 &apos;&apos;&apos; It checks for a specific response to a particular set of inputs.
43 &apos;&apos;&apos; A test case in the UnitTest service is represented by a Basic Sub.
44 &apos;&apos;&apos; The name of the Sub starts conventionally with &quot;Test_&quot;.
45 &apos;&apos;&apos; The test fails if one of the included AssertXXX methods returns False
46 &apos;&apos;&apos; - Test Suite
47 &apos;&apos;&apos; A test suite is a collection of test cases that should be executed together.
48 &apos;&apos;&apos; A test suite is represented by a Basic module.
49 &apos;&apos;&apos; A suite may include the tasks needed to prepare one or more tests, and any associated cleanup actions.
50 &apos;&apos;&apos; This may involve, for example, creating temporary files or directories, opening a document, loading libraries.
51 &apos;&apos;&apos; Conventionally those tasks are part pf the SetUp&apos;) and TearDown() methods.
52 &apos;&apos;&apos; - Unit test
53 &apos;&apos;&apos; A full unit test is a set of test suites (each suite in a separate Basic module),
54 &apos;&apos;&apos; each of them being a set of test cases (each case is located in a separate Basic Sub).
55 &apos;&apos;&apos;
56 &apos;&apos;&apos; Two modes:
57 &apos;&apos;&apos; Beside the normal mode (&quot;full mode&quot;), using test suites and test cases, a second mode exists, called &quot;simple mode&quot;
58 &apos;&apos;&apos; limited to the use exclusively of the Assert...() methods.
59 &apos;&apos;&apos; Their boolean returned value may support the execution of limited unit tests.
60 &apos;&apos;&apos;
61 &apos;&apos;&apos; Service invocation examples:
62 &apos;&apos;&apos; In full mode, the service creation is external to test cases
63 &apos;&apos;&apos; Dim myUnitTest As Variant
64 &apos;&apos;&apos; myUnitTest = CreateScriptService(&quot;UnitTest&quot;, ThisComponent, &quot;Tests&quot;)
65 &apos;&apos;&apos; &apos; Test code is in the library &quot;Tests&quot; located in the current document
66 &apos;&apos;&apos; In simple mode, the service creation is internal to every test case
67 &apos;&apos;&apos; Dim myUnitTest As Variant
68 &apos;&apos;&apos; myUnitTest = CreateScriptService(&quot;UnitTest&quot;)
69 &apos;&apos;&apos; With myUnitTest
70 &apos;&apos;&apos; If Not .AssertTrue(...) Then ... &apos; Only calls to the Assert...() methods are allowed
71 &apos;&apos;&apos; &apos; ...
72 &apos;&apos;&apos; .Dispose()
73 &apos;&apos;&apos; End With
74 &apos;&apos;&apos;
75 &apos;&apos;&apos; Minimalist full mode example
76 &apos;&apos;&apos; Code to be tested (stored in library &quot;Standard&quot; of document &quot;MyDoc.ods&quot;) :
77 &apos;&apos;&apos; Function ArraySize(arr As Variant) As Long
78 &apos;&apos;&apos; If IsArray(arr) Then ArraySize = UBound(arr) - LBound(arr) + 1 Else ArraySize = -1
79 &apos;&apos;&apos; End Function
80 &apos;&apos;&apos; Test code (stored in module &quot;AllTests&quot; of library &quot;Tests&quot; of document &quot;MyDoc.ods&quot;) :
81 &apos;&apos;&apos; Sub Main() &apos; Sub to trigger manually, f.i. from the Tools + Run Macro tabbed bar
82 &apos;&apos;&apos; GlobalScope.BasicLibraries.loadLibrary(&quot;ScriptForge&quot;)
83 &apos;&apos;&apos; Dim test : test = CreateScriptService(&quot;UnitTest&quot;, ThisComponent, &quot;Tests&quot;)
84 &apos;&apos;&apos; test.RunTest(&quot;AllTests&quot;) &apos; AllTests is a module name ; test cases are named &quot;Test_*&quot; (default)
85 &apos;&apos;&apos; test.Dispose()
86 &apos;&apos;&apos; End Sub
87 &apos;&apos;&apos; REM ------------------------------------------------------------------------------
88 &apos;&apos;&apos; Sub Setup(test) &apos; The unittest service is passed as argument
89 &apos;&apos;&apos; &apos; Optional Sub to initialize processing of the actual test suite
90 &apos;&apos;&apos; Dim exc : exc = CreateScriptService(&quot;Exception&quot;)
91 &apos;&apos;&apos; exc.Console(Modal := False) &apos; Watch test progress in the console
92 &apos;&apos;&apos; End Sub
93 &apos;&apos;&apos; REM ------------------------------------------------------------------------------
94 &apos;&apos;&apos; Sub Test_ArraySize(test)
95 &apos;&apos;&apos; On Local Error GoTo CatchErr
96 &apos;&apos;&apos; test.AssertEqual(ArraySize(10), -1, &quot;When not array&quot;)
97 &apos;&apos;&apos; test.AssertEqual(ArraySize(Array(1, 2, 3)), 3, &quot;When simple array&quot;)
98 &apos;&apos;&apos; test.AssertEqual(ArraySize(DimArray(3)), 4, &quot;When array with empty items&quot;)
99 &apos;&apos;&apos; Exit Sub
100 &apos;&apos;&apos; CatchErr:
101 &apos;&apos;&apos; test.ReportError(&quot;ArraySize() is corrupt&quot;)
102 &apos;&apos;&apos; End Sub
103 &apos;&apos;&apos; REM ------------------------------------------------------------------------------
104 &apos;&apos;&apos; Sub TearDown(test)
105 &apos;&apos;&apos; &apos; Optional Sub to finalize processing of the actual test suite
106 &apos;&apos;&apos; End Sub
107 &apos;&apos;&apos;
108 &apos;&apos;&apos; Error handling
109 &apos;&apos;&apos; To support the debugging of the tested code, the UnitTest service, in cases of
110 &apos;&apos;&apos; - assertion failure
111 &apos;&apos;&apos; - Basic run-time error in the tested code
112 &apos;&apos;&apos; - Basic run-time error in the testing code (the unit tests)
113 &apos;&apos;&apos; will comment the error location and description in a message box and in the console log,
114 &apos;&apos;&apos; providing every test case (in either mode) implements an error handler containing at least:
115 &apos;&apos;&apos; Sub Test_Case1(test As Variant)
116 &apos;&apos;&apos; On Local Error GoTo Catch
117 &apos;&apos;&apos; &apos; ... (AssertXXX(), Fail(), ...)
118 &apos;&apos;&apos; Exit Sub
119 &apos;&apos;&apos; Catch:
120 &apos;&apos;&apos; test.ReportError()
121 &apos;&apos;&apos; End Sub
122 &apos;&apos;&apos;
123 &apos;&apos;&apos; Detailed user documentation:
124 &apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_unittest.html?DbPAR=BASIC
125 &apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
127 REM ================================================================== EXCEPTIONS
129 Private Const UNITTESTMETHODERROR = &quot;UNITTESTMETHODERROR&quot;
131 REM ============================================================= PRIVATE MEMBERS
133 Private [Me] As Object
134 Private [_Parent] As Object
135 Private ObjectType As String &apos; Must be &quot;UNITTEST&quot;
136 Private ServiceName As String
138 &apos; Testing code
139 Private LibrariesContainer As String &apos; Document or user Basic library containing the test library
140 Private Scope As String &apos; Scope when running a Basic script with Session.ExecuteBasicScript()
141 Private Libraries As Variant &apos; Set of libraries
142 Private LibraryName As String &apos; Name of the library containing the test code
143 Private LibraryIndex As Integer &apos; Index in Libraries
144 Private Modules As Variant &apos; Set of modules
145 Private ModuleNames As Variant &apos; Set of module names
146 Private MethodNames As Variant &apos; Set of methods in a given module
148 &apos; Internals
149 Private _Verbose As Boolean &apos; When True, every assertion is reported,failing or not
150 Private _LongMessage As Boolean &apos; When False, only the message provided by the tester is considered
151 &apos; When True (default), that message is appended to the standard message
152 Private _WhenAssertionFails As Integer &apos; Determines what to do when a test fails
154 &apos; Test status
155 Private _Status As Integer &apos; 0 = standby
156 &apos; 1 = test suite started
157 &apos; 2 = setup started
158 &apos; 3 = test case started
159 &apos; 4 = teardown started
160 Private _ExecutionMode As Integer &apos; 1 = Test started with RunTest()
161 &apos; 2 = Test started with CreateScriptService() Only Assert() methods allowed
162 Private _Module As String &apos; Exact name of module currently running
163 Private _TestCase As String &apos; Exact name of test case currently running
164 Private _ReturnCode As Integer &apos; 0 = Normal end
165 &apos; 1 = Assertion failed
166 &apos; 2 = Skip request (in Setup() only)
167 &apos;-1 = abnormal end
168 Private _FailedAssert As String &apos; Assert function that returned a failure
170 &apos; Timers
171 Private TestTimer As Object &apos; Started by CreateScriptService()
172 Private SuiteTimer As Object &apos; Started by RunTest()
173 Private CaseTimer As Object &apos; Started by new case
175 &apos; Services
176 Private Exception As Object &apos; SF_Exception
177 Private Session As Object &apos; SF_Session
179 REM ============================================================ MODULE CONSTANTS
181 &apos; When assertion fails constants: error is reported + ...
182 Global Const FAILIGNORE = 0 &apos; Ignore the failure
183 Global Const FAILSTOPSUITE = 1 &apos; Module TearDown is executed, then next suite may be started (default in full mode)
184 Global Const FAILIMMEDIATESTOP = 2 &apos; Stop immediately (default in simple mode)
186 &apos; Unit tests status (internal use only =&gt; not Global)
187 Const STATUSSTANDBY = 0 &apos; No test active
188 Const STATUSSUITESTARTED = 1 &apos; RunTest() started
189 Const STATUSSETUP = 2 &apos; A Setup() method is running
190 Const STATUSTESTCASE = 3 &apos; A test case is running
191 Const STATUSTEARDOWN = 4 &apos; A TearDown() method is running
193 &apos; Return codes
194 Global Const RCNORMALEND = 0 &apos; Normal end of test or test not started
195 Global Const RCASSERTIONFAILED = 1 &apos; An assertion within a test case returned False
196 Global Const RCSKIPTEST = 2 &apos; A SkipTest() was issued by a Setup() method
197 Global Const RCABORTTEST = 3 &apos; Abnormal end of test
199 &apos; Execution modes
200 Global Const FULLMODE = 1 &apos; 1 = Test started with RunTest()
201 Global Const SIMPLEMODE = 2 &apos; 2 = Test started with CreateScriptService() Only Assert() methods allowed
203 Const INVALIDPROCEDURECALL = &quot;5&quot; &apos; Artificial error raised when an assertion fails
205 REM ===================================================== CONSTRUCTOR/DESTRUCTOR
207 REM -----------------------------------------------------------------------------
208 Private Sub Class_Initialize()
209 Set [Me] = Nothing
210 Set [_Parent] = Nothing
211 ObjectType = &quot;UNITTEST&quot;
212 ServiceName = &quot;SFUnitTests.UnitTest&quot;
213 LibrariesContainer = &quot;&quot;
214 Scope = &quot;&quot;
215 Libraries = Array()
216 LibraryName = &quot;&quot;
217 LibraryIndex = -1
218 _Verbose = False
219 _LongMessage = True
220 _WhenAssertionFails = -1
221 _Status = STATUSSTANDBY
222 _ExecutionMode = SIMPLEMODE
223 _Module = &quot;&quot;
224 _TestCase = &quot;&quot;
225 _ReturnCode = RCNORMALEND
226 _FailedAssert = &quot;&quot;
227 Set TestTimer = Nothing
228 Set SuiteTimer = Nothing
229 Set CaseTimer = Nothing
230 Set Exception = ScriptForge.SF_Exception &apos; Do not use CreateScriptService to allow New SF_UnitTest from other libraries
231 Set Session = ScriptForge.SF_Session
232 End Sub &apos; SFUnitTests.SF_UnitTest Constructor
234 REM -----------------------------------------------------------------------------
235 Private Sub Class_Terminate()
236 If Not IsNull(CaseTimer) Then CaseTimer = CaseTimer.Dispose()
237 If Not IsNull(SuiteTimer) Then SuiteTimer = SuiteTimer.Dispose()
238 If Not IsNull(TestTimer) Then TestTimer = TestTimer.Dispose()
239 Call Class_Initialize()
240 End Sub &apos; SFUnitTests.SF_UnitTest Destructor
242 REM -----------------------------------------------------------------------------
243 Public Function Dispose() As Variant
244 Call Class_Terminate()
245 Set Dispose = Nothing
246 End Function &apos; SFUnitTests.SF_UnitTest Explicit destructor
248 REM ================================================================== PROPERTIES
250 REM -----------------------------------------------------------------------------
251 Property Get LongMessage() As Variant
252 &apos;&apos;&apos; When False, only the message provided by the tester is considered
253 &apos;&apos;&apos; When True (default), that message is appended to the standard message
254 LongMessage = _PropertyGet(&quot;LongMessage&quot;)
255 End Property &apos; SFUnitTests.SF_UnitTest.LongMessage (get)
257 REM -----------------------------------------------------------------------------
258 Property Let LongMessage(Optional ByVal pvLongMessage As Variant)
259 &apos;&apos;&apos; Set the updatable property LongMessage
260 _PropertySet(&quot;LongMessage&quot;, pvLongMessage)
261 End Property &apos; SFUnitTests.SF_UnitTest.LongMessage (let)
263 REM -----------------------------------------------------------------------------
264 Property Get ReturnCode() As Integer
265 &apos;&apos;&apos; RCNORMALEND = 0 &apos; Normal end of test or test not started
266 &apos;&apos;&apos; RCASSERTIONFAILED = 1 &apos; An assertion within a test case returned False
267 &apos;&apos;&apos; RCSKIPTEST = 2 &apos; A SkipTest() was issued by a Setup() method
268 &apos;&apos;&apos; RCABORTTEST = 3 &apos; Abnormal end of test
269 ReturnCode = _PropertyGet(&quot;ReturnCode&quot;)
270 End Property &apos; SFUnitTests.SF_UnitTest.ReturnCode (get)
272 REM -----------------------------------------------------------------------------
273 Property Get Verbose() As Variant
274 &apos;&apos;&apos; The Verbose property indicates if all assertions (True AND False) are reported
275 Verbose = _PropertyGet(&quot;Verbose&quot;)
276 End Property &apos; SFUnitTests.SF_UnitTest.Verbose (get)
278 REM -----------------------------------------------------------------------------
279 Property Let Verbose(Optional ByVal pvVerbose As Variant)
280 &apos;&apos;&apos; Set the updatable property Verbose
281 _PropertySet(&quot;Verbose&quot;, pvVerbose)
282 End Property &apos; SFUnitTests.SF_UnitTest.Verbose (let)
284 REM -----------------------------------------------------------------------------
285 Property Get WhenAssertionFails() As Variant
286 &apos;&apos;&apos; What when an AssertXXX() method returns False
287 &apos;&apos;&apos; FAILIGNORE = 0 &apos; Ignore the failure
288 &apos;&apos;&apos; FAILSTOPSUITE = 1 &apos; Module TearDown is executed, then next suite may be started (default in FULL mode)
289 &apos;&apos;&apos; FAILIMMEDIATESTOP = 2 &apos; Stop immediately (default in SIMPLE mode)
290 &apos;&apos;&apos; In simple mode, only FAILIGNORE and FAILIMMEDIATESTOP are allowed.
291 &apos;&apos;&apos; In both modes, when WhenAssertionFails has not the value FAILIGNORE,
292 &apos;&apos;&apos; each test case MUST have a run-time error handler calling the ReportError() method.
293 &apos;&apos;&apos; Example:
294 &apos;&apos;&apos; Sub Test_sometest(Optional test)
295 &apos;&apos;&apos; On Local Error GoTo CatchError
296 &apos;&apos;&apos; &apos; ... one or more assert verbs
297 &apos;&apos;&apos; Exit Sub
298 &apos;&apos;&apos; CatchError:
299 &apos;&apos;&apos; test.ReportError()
300 &apos;&apos;&apos; End Sub
301 WhenAssertionFails = _PropertyGet(&quot;WhenAssertionFails&quot;)
302 End Property &apos; SFUnitTests.SF_UnitTest.WhenAssertionFails (get)
304 REM -----------------------------------------------------------------------------
305 Property Let WhenAssertionFails(Optional ByVal pvWhenAssertionFails As Variant)
306 &apos;&apos;&apos; Set the updatable property WhenAssertionFails
307 _PropertySet(&quot;WhenAssertionFails&quot;, pvWhenAssertionFails)
308 End Property &apos; SFUnitTests.SF_UnitTest.WhenAssertionFails (let)
310 REM ===================================================================== METHODS
312 REM -----------------------------------------------------------------------------
313 Public Function AssertAlmostEqual(Optional ByRef A As Variant _
314 , Optional ByRef B As Variant _
315 , Optional ByVal Tolerance As Variant _
316 , Optional ByVal Message As Variant _
317 ) As Boolean
318 &apos;&apos;&apos; Returns True when A and B are numerical values and are found close to each other.
319 &apos;&apos;&apos; It is typically used to compare very large or very small numbers.
320 &apos;&apos;&apos; Equality is confirmed when
321 &apos;&apos;&apos; - A and B can be converted to doubles
322 &apos;&apos;&apos; - The absolute difference between a and b, relative to the larger absolute value of a or b,
323 &apos;&apos;&apos; is lower or equal to the tolerance. The default tolerance is 1E-09,
324 &apos;&apos;&apos; Examples: 1E+12 and 1E+12 + 100 are almost equal
325 &apos;&apos;&apos; 1E-20 and 2E-20 are not almost equal
326 &apos;&apos;&apos; 100 and 95 are almost equal when Tolerance = 0.05
328 Dim bAssert As Boolean &apos; Return value
329 Const cstTolerance = 1E-09
330 Const cstThisSub = &quot;UnitTest.AssertAlmostEqual&quot;
331 Const cstSubArgs = &quot;A, B, [Tolerance=1E-09], [Message=&quot;&quot;&quot;&quot;]&quot;
333 Check:
334 If IsMissing(A) Then A = Empty
335 If IsMissing(B) Then B = Empty
336 If IsMissing(Tolerance) Then Tolerance = cstTolerance
337 If IsMissing(Message) Then Message = &quot;&quot;
338 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
339 If Not ScriptForge.SF_Utils._Validate(Tolerance, &quot;Tolerance&quot;, ScriptForge.V_NUMERIC) Then GoTo Catch
341 Try:
342 bAssert = _Assert(&quot;AssertAlmostEqual&quot;, True, A, B, Message, Tolerance)
344 Finally:
345 AssertAlmostEqual = bAssert
346 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
347 Exit Function
348 Catch:
349 bAssert = False
350 GoTo Finally
351 End Function &apos; SFUnitTests.SF_UnitTest.AssertAlmostEqual
353 REM -----------------------------------------------------------------------------
354 Public Function AssertEqual(Optional ByRef A As Variant _
355 , Optional ByRef B As Variant _
356 , Optional ByVal Message As Variant _
357 ) As Boolean
358 &apos;&apos;&apos; Returns True when A and B are found equal.
359 &apos;&apos;&apos; Equality is confirmed when
360 &apos;&apos;&apos; If A and B are scalars:
361 &apos;&apos;&apos; They should have the same VarType or both be numeric
362 &apos;&apos;&apos; Booleans and numeric values are compared with the = operator
363 &apos;&apos;&apos; Strings are compared with the StrComp() builtin function. The comparison is case-sensitive
364 &apos;&apos;&apos; Dates and times are compared up to the second
365 &apos;&apos;&apos; Null, Empty and Nothing are not equal, but AssertEqual(Nothing, Nothing) returns True
366 &apos;&apos;&apos; UNO objects are compared with the EqualUnoObjects() method
367 &apos;&apos;&apos; Basic objects are NEVER equal
368 &apos;&apos;&apos; If A and B are arrays:
369 &apos;&apos;&apos; They should have the same number of dimensions (maximum 2)
370 &apos;&apos;&apos; The lower and upper bounds must be identical for each dimension
371 &apos;&apos;&apos; Two empty arrays are equal
372 &apos;&apos;&apos; Their items must be equal one by one
374 Dim bAssert As Boolean &apos; Return value
375 Const cstThisSub = &quot;UnitTest.AssertEqual&quot;
376 Const cstSubArgs = &quot;A, B, [Message=&quot;&quot;&quot;&quot;]&quot;
378 Check:
379 If IsMissing(A) Then A = Empty
380 If IsMissing(B) Then B = Empty
381 If IsMissing(Message) Then Message = &quot;&quot;
382 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
384 Try:
385 bAssert = _Assert(&quot;AssertEqual&quot;, True, A, B, Message)
387 Finally:
388 AssertEqual = bAssert
389 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
390 Exit Function
391 End Function &apos; SFUnitTests.SF_UnitTest.AssertEqual
393 REM -----------------------------------------------------------------------------
394 Public Function AssertFalse(Optional ByRef A As Variant _
395 , Optional ByVal Message As Variant _
396 ) As Boolean
397 &apos;&apos;&apos; Returns True when A is a Boolean and its value is False
399 Dim bAssert As Boolean &apos; Return value
400 Const cstThisSub = &quot;UnitTest.AssertFalse&quot;
401 Const cstSubArgs = &quot;A, [Message=&quot;&quot;&quot;&quot;]&quot;
403 Check:
404 If IsMissing(A) Then A = Empty
405 If IsMissing(Message) Then Message = &quot;&quot;
406 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
408 Try:
409 bAssert = _Assert(&quot;AssertFalse&quot;, True, A, Empty, Message)
411 Finally:
412 AssertFalse = bAssert
413 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
414 Exit Function
415 End Function &apos; SFUnitTests.SF_UnitTest.AssertFalse
417 REM -----------------------------------------------------------------------------
418 Public Function AssertGreater(Optional ByRef A As Variant _
419 , Optional ByRef B As Variant _
420 , Optional ByVal Message As Variant _
421 ) As Boolean
422 &apos;&apos;&apos; Returns True when A is greater than B.
423 &apos;&apos;&apos; To compare A and B:
424 &apos;&apos;&apos; They should have the same VarType or both be numeric
425 &apos;&apos;&apos; Eligible datatypes are String, Date or numeric.
426 &apos;&apos;&apos; String comparisons are case-sensitive.
428 Dim bAssert As Boolean &apos; Return value
429 Const cstThisSub = &quot;UnitTest.AssertGreater&quot;
430 Const cstSubArgs = &quot;A, B, [Message=&quot;&quot;&quot;&quot;]&quot;
432 Check:
433 If IsMissing(A) Then A = Empty
434 If IsMissing(B) Then B = Empty
435 If IsMissing(Message) Then Message = &quot;&quot;
436 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
438 Try:
439 bAssert = _Assert(&quot;AssertGreater&quot;, True, A, B, Message)
441 Finally:
442 AssertGreater = bAssert
443 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
444 Exit Function
445 End Function &apos; SFUnitTests.SF_UnitTest.AssertGreater
447 REM -----------------------------------------------------------------------------
448 Public Function AssertGreaterEqual(Optional ByRef A As Variant _
449 , Optional ByRef B As Variant _
450 , Optional ByVal Message As Variant _
451 ) As Boolean
452 &apos;&apos;&apos; Returns True when A is greater than or equal to B.
453 &apos;&apos;&apos; To compare A and B:
454 &apos;&apos;&apos; They should have the same VarType or both be numeric
455 &apos;&apos;&apos; Eligible datatypes are String, Date or numeric.
456 &apos;&apos;&apos; String comparisons are case-sensitive.
458 Dim bAssert As Boolean &apos; Return value
459 Const cstThisSub = &quot;UnitTest.AssertGreaterEqual&quot;
460 Const cstSubArgs = &quot;A, B, [Message=&quot;&quot;&quot;&quot;]&quot;
462 Check:
463 If IsMissing(A) Then A = Empty
464 If IsMissing(B) Then B = Empty
465 If IsMissing(Message) Then Message = &quot;&quot;
466 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
468 Try:
469 bAssert = _Assert(&quot;AssertGreaterEqual&quot;, True, A, B, Message)
471 Finally:
472 AssertGreaterEqual = bAssert
473 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
474 Exit Function
475 End Function &apos; SFUnitTests.SF_UnitTest.AssertGreaterEqual
477 REM -----------------------------------------------------------------------------
478 Public Function AssertIn(Optional ByRef A As Variant _
479 , Optional ByRef B As Variant _
480 , Optional ByVal Message As Variant _
481 ) As Boolean
482 &apos;&apos;&apos; Returns True when A, a string, is found within B
483 &apos;&apos;&apos; B may be a 1D array, a ScriptForge dictionary or a string.
484 &apos;&apos;&apos; When B is an array, A may be a date or a numeric value.
485 &apos;&apos;&apos; String comparisons are case-sensitive.
487 Dim bAssert As Boolean &apos; Return value
488 Const cstThisSub = &quot;UnitTest.AssertIn&quot;
489 Const cstSubArgs = &quot;A, B, [Message=&quot;&quot;&quot;&quot;]&quot;
491 Check:
492 If IsMissing(A) Then A = Empty
493 If IsMissing(B) Then B = Empty
494 If IsMissing(Message) Then Message = &quot;&quot;
495 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
497 Try:
498 bAssert = _Assert(&quot;AssertIn&quot;, True, A, B, Message)
500 Finally:
501 AssertIn = bAssert
502 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
503 Exit Function
504 End Function &apos; SFUnitTests.SF_UnitTest.AssertIn
506 REM -----------------------------------------------------------------------------
507 Public Function AssertIsInstance(Optional ByRef A As Variant _
508 , Optional ByRef ObjectType As Variant _
509 , Optional ByVal Message As Variant _
510 ) As Boolean
511 &apos;&apos;&apos; Returns True when A is an object instance of the class ObjectType or a variable of type ObjectType.
512 &apos;&apos;&apos; A may be:
513 &apos;&apos;&apos; - a ScriptForge object
514 &apos;&apos;&apos; ObjectType is a string like &quot;DICTIONARY&quot;, &quot;calc&quot;, &quot;Dialog&quot;, &quot;exception&quot;, etc.
515 &apos;&apos;&apos; - a UNO object
516 &apos;&apos;&apos; ObjectType is a string identical with values returned by the SF_Session.UnoObjectType()
517 &apos;&apos;&apos; - any variable, providing it is neither an object nor an array
518 &apos;&apos;&apos; ObjectType is a string identifying a value returned by the TypeName() builtin function
519 &apos;&apos;&apos; - an array
520 &apos;&apos;&apos; ObjectType is expected to be &quot;array&quot;
522 Dim bAssert As Boolean &apos; Return value
523 Const cstThisSub = &quot;UnitTest.AssertIsInstance&quot;
524 Const cstSubArgs = &quot;A, ObjectType, [Message=&quot;&quot;&quot;&quot;]&quot;
526 Check:
527 If IsMissing(A) Then A = Empty
528 If IsMissing(ObjectType) Then ObjectType = Empty
529 If IsMissing(Message) Then Message = &quot;&quot;
530 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
531 If Not ScriptForge.SF_Utils._Validate(ObjectType, &quot;ObjectType&quot;, V_STRING) Then GoTo Catch
534 Try:
535 bAssert = _Assert(&quot;AssertIsInstance&quot;, True, A, Empty, Message, ObjectType)
537 Finally:
538 AssertIsInstance = bAssert
539 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
540 Exit Function
541 Catch:
542 bAssert = False
543 GoTo Finally
544 End Function &apos; SFUnitTests.SF_UnitTest.AssertIsInstance
546 REM -----------------------------------------------------------------------------
547 Public Function AssertIsNothing(Optional ByRef A As Variant _
548 , Optional ByVal Message As Variant _
549 ) As Boolean
550 &apos;&apos;&apos; Returns True when A is an object that has the Nothing value
552 Dim bAssert As Boolean &apos; Return value
553 Const cstThisSub = &quot;UnitTest.AssertIsNothing&quot;
554 Const cstSubArgs = &quot;A, [Message=&quot;&quot;&quot;&quot;]&quot;
556 Check:
557 If IsMissing(A) Then A = Empty
558 If IsMissing(Message) Then Message = &quot;&quot;
559 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
561 Try:
562 bAssert = _Assert(&quot;AssertIsNothing&quot;, True, A, Empty, Message)
564 Finally:
565 AssertIsNothing = bAssert
566 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
567 Exit Function
568 End Function &apos; SFUnitTests.SF_UnitTest.AssertIsNothing
570 REM -----------------------------------------------------------------------------
571 Public Function AssertIsNull(Optional ByRef A As Variant _
572 , Optional ByVal Message As Variant _
573 ) As Boolean
574 &apos;&apos;&apos; Returns True when A has the Null value
576 Dim bAssert As Boolean &apos; Return value
577 Const cstThisSub = &quot;UnitTest.AssertIsNull&quot;
578 Const cstSubArgs = &quot;A, [Message=&quot;&quot;&quot;&quot;]&quot;
580 Check:
581 If IsMissing(A) Then A = Empty
582 If IsMissing(Message) Then Message = &quot;&quot;
583 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
585 Try:
586 bAssert = _Assert(&quot;AssertIsNull&quot;, True, A, Empty, Message)
588 Finally:
589 AssertIsNull = bAssert
590 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
591 Exit Function
592 End Function &apos; SFUnitTests.SF_UnitTest.AssertIsNull
594 REM -----------------------------------------------------------------------------
595 Public Function AssertLess(Optional ByRef A As Variant _
596 , Optional ByRef B As Variant _
597 , Optional ByVal Message As Variant _
598 ) As Boolean
599 &apos;&apos;&apos; Returns True when A is less than B.
600 &apos;&apos;&apos; To compare A and B:
601 &apos;&apos;&apos; They should have the same VarType or both be numeric
602 &apos;&apos;&apos; Eligible datatypes are String, Date or numeric.
603 &apos;&apos;&apos; String comparisons are case-sensitive.
605 Dim bAssert As Boolean &apos; Return value
606 Const cstThisSub = &quot;UnitTest.AssertLess&quot;
607 Const cstSubArgs = &quot;A, B, [Message=&quot;&quot;&quot;&quot;]&quot;
609 Check:
610 If IsMissing(A) Then A = Empty
611 If IsMissing(B) Then B = Empty
612 If IsMissing(Message) Then Message = &quot;&quot;
613 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
615 Try:
616 bAssert = _Assert(&quot;AssertLess&quot;, False, A, B, Message)
618 Finally:
619 AssertLess = bAssert
620 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
621 Exit Function
622 End Function &apos; SFUnitTests.SF_UnitTest.AssertLess
624 REM -----------------------------------------------------------------------------
625 Public Function AssertLessEqual(Optional ByRef A As Variant _
626 , Optional ByRef B As Variant _
627 , Optional ByVal Message As Variant _
628 ) As Boolean
629 &apos;&apos;&apos; Returns True when A is less than or equal to B.
630 &apos;&apos;&apos; To compare A and B:
631 &apos;&apos;&apos; They should have the same VarType or both be numeric
632 &apos;&apos;&apos; Eligible datatypes are String, Date or numeric.
633 &apos;&apos;&apos; String comparisons are case-sensitive.
635 Dim bAssert As Boolean &apos; Return value
636 Const cstThisSub = &quot;UnitTest.AssertLessEqual&quot;
637 Const cstSubArgs = &quot;A, B, [Message=&quot;&quot;&quot;&quot;]&quot;
639 Check:
640 If IsMissing(A) Then A = Empty
641 If IsMissing(B) Then B = Empty
642 If IsMissing(Message) Then Message = &quot;&quot;
643 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
645 Try:
646 bAssert = _Assert(&quot;AssertLessEqual&quot;, False, A, B, Message)
648 Finally:
649 AssertLessEqual = bAssert
650 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
651 Exit Function
652 End Function &apos; SFUnitTests.SF_UnitTest.AssertLessEqual
654 REM -----------------------------------------------------------------------------
655 Public Function AssertLike(Optional ByRef A As Variant _
656 , Optional ByRef Pattern As Variant _
657 , Optional ByVal Message As Variant _
658 ) As Boolean
659 &apos;&apos;&apos; Returns True if string A matches a given pattern containing wildcards
660 &apos;&apos;&apos; Admitted wildcard are: the &quot;?&quot; represents any single character
661 &apos;&apos;&apos; the &quot;*&quot; represents zero, one, or multiple characters
662 &apos;&apos;&apos; The comparison is case-sensitive.
664 Dim bAssert As Boolean &apos; Return value
665 Const cstThisSub = &quot;UnitTest.AssertLike&quot;
666 Const cstSubArgs = &quot;A, Pattern, [Message=&quot;&quot;&quot;&quot;]&quot;
668 Check:
669 If IsMissing(A) Then A = Empty
670 If IsMissing(Pattern) Then Pattern = &quot;&quot;
671 If IsMissing(Message) Then Message = &quot;&quot;
672 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
673 If Not ScriptForge.SF_Utils._Validate(Pattern, &quot;Pattern&quot;, V_STRING) Then GoTo Catch
675 Try:
676 bAssert = _Assert(&quot;AssertLike&quot;, True, A, Empty, Message, Pattern)
678 Finally:
679 AssertLike = bAssert
680 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
681 Exit Function
682 Catch:
683 bAssert = False
684 GoTo Finally
685 End Function &apos; SFUnitTests.SF_UnitTest.AssertLike
687 REM -----------------------------------------------------------------------------
688 Public Function AssertNotAlmostEqual(Optional ByRef A As Variant _
689 , Optional ByRef B As Variant _
690 , Optional ByVal Tolerance As Variant _
691 , Optional ByVal Message As Variant _
692 ) As Boolean
693 &apos;&apos;&apos; Returns True when A and B are numerical values and are not found close to each other.
694 &apos;&apos;&apos; Read about almost equality in the comments linked to the AssertEqual() method.
696 Dim bAssert As Boolean &apos; Return value
697 Const cstTolerance = 1E-09
698 Const cstThisSub = &quot;UnitTest.AssertNotAlmostEqual&quot;
699 Const cstSubArgs = &quot;A, B, [Tolerance=1E-09], [Message=&quot;&quot;&quot;&quot;]&quot;
701 Check:
702 If IsMissing(A) Then A = Empty
703 If IsMissing(B) Then B = Empty
704 If IsMissing(Tolerance) Then Tolerance = cstTolerance
705 If IsMissing(Message) Then Message = &quot;&quot;
706 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
707 If Not ScriptForge.SF_Utils._Validate(Tolerance, &quot;Tolerance&quot;, ScriptForge.V_NUMERIC) Then GoTo Catch
709 Try:
710 bAssert = _Assert(&quot;AssertNotAlmostEqual&quot;, False, A, B, Message, Tolerance)
712 Finally:
713 AssertNotAlmostEqual = bAssert
714 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
715 Exit Function
716 Catch:
717 bAssert = False
718 GoTo Finally
719 End Function &apos; SFUnitTests.SF_UnitTest.AssertNotAlmostEqual
721 REM -----------------------------------------------------------------------------
722 Public Function AssertNotEqual(Optional ByRef A As Variant _
723 , Optional ByRef B As Variant _
724 , Optional ByVal Message As Variant _
725 ) As Boolean
726 &apos;&apos;&apos; Returns True when A and B are found unequal.
727 &apos;&apos;&apos; Read about equality in the comments linked to the AssertEqual() method.
729 Dim bAssert As Boolean &apos; Return value
730 Const cstThisSub = &quot;UnitTest.AssertNotEqual&quot;
731 Const cstSubArgs = &quot;A, B, [Message=&quot;&quot;&quot;&quot;]&quot;
733 Check:
734 If IsMissing(A) Then A = Empty
735 If IsMissing(B) Then B = Empty
736 If IsMissing(Message) Then Message = &quot;&quot;
737 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
739 Try:
740 bAssert = _Assert(&quot;AssertNotEqual&quot;, False, A, B, Message)
742 Finally:
743 AssertNotEqual = bAssert
744 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
745 Exit Function
746 End Function &apos; SFUnitTests.SF_UnitTest.AssertNotEqual
748 REM -----------------------------------------------------------------------------
749 Public Function AssertNotIn(Optional ByRef A As Variant _
750 , Optional ByRef B As Variant _
751 , Optional ByVal Message As Variant _
752 ) As Boolean
753 &apos;&apos;&apos; Returns True when A, a string, is not found within B
754 &apos;&apos;&apos; B may be a 1D array, a ScriptForge dictionary or a string.
755 &apos;&apos;&apos; When B is an array, A may be a date or a numeric value.
756 &apos;&apos;&apos; String comparisons are case-sensitive.
758 Dim bAssert As Boolean &apos; Return value
759 Const cstThisSub = &quot;UnitTest.AssertNotIn&quot;
760 Const cstSubArgs = &quot;A, B, [Message=&quot;&quot;&quot;&quot;]&quot;
762 Check:
763 If IsMissing(A) Then A = Empty
764 If IsMissing(B) Then B = Empty
765 If IsMissing(Message) Then Message = &quot;&quot;
766 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
768 Try:
769 bAssert = _Assert(&quot;AssertNotIn&quot;, False, A, B, Message)
771 Finally:
772 AssertNotIn = bAssert
773 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
774 Exit Function
775 End Function &apos; SFUnitTests.SF_UnitTest.AssertNotIn
777 REM -----------------------------------------------------------------------------
778 Public Function AssertNotInstance(Optional ByRef A As Variant _
779 , Optional ByRef ObjectType As Variant _
780 , Optional ByVal Message As Variant _
781 ) As Boolean
782 &apos;&apos;&apos; Returns True when A is an object instance of the class ObjectType or a variable of type ObjectType.
783 &apos;&apos;&apos; More details to be read under the AssertInstance() function.
785 Dim bAssert As Boolean &apos; Return value
786 Const cstThisSub = &quot;UnitTest.AssertNotInstance&quot;
787 Const cstSubArgs = &quot;A, ObjectType, [Message=&quot;&quot;&quot;&quot;]&quot;
789 Check:
790 If IsMissing(A) Then A = Empty
791 If IsMissing(ObjectType) Then ObjectType = Empty
792 If IsMissing(Message) Then Message = &quot;&quot;
793 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
794 If Not ScriptForge.SF_Utils._Validate(ObjectType, &quot;ObjectType&quot;, V_STRING) Then GoTo Catch
796 Try:
797 bAssert = _Assert(&quot;AssertNotInstance&quot;, False, A, Empty, Message, ObjectType)
799 Finally:
800 AssertNotInstance = bAssert
801 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
802 Exit Function
803 Catch:
804 bAssert = False
805 GoTo Finally
806 End Function &apos; SFUnitTests.SF_UnitTest.AssertNotInstance
808 REM -----------------------------------------------------------------------------
809 Public Function AssertNotLike(Optional ByRef A As Variant _
810 , Optional ByRef Pattern As Variant _
811 , Optional ByVal Message As Variant _
812 ) As Boolean
813 &apos;&apos;&apos; Returns True if A is not a string or does not match a given pattern containing wildcards
814 &apos;&apos;&apos; Admitted wildcard are: the &quot;?&quot; represents any single character
815 &apos;&apos;&apos; the &quot;*&quot; represents zero, one, or multiple characters
816 &apos;&apos;&apos; The comparison is case-sensitive.
818 Dim bAssert As Boolean &apos; Return value
819 Const cstThisSub = &quot;UnitTest.AssertNotLike&quot;
820 Const cstSubArgs = &quot;A, Pattern, [Message=&quot;&quot;&quot;&quot;]&quot;
822 Check:
823 If IsMissing(A) Then A = Empty
824 If IsMissing(Pattern) Then Pattern = &quot;&quot;
825 If IsMissing(Message) Then Message = &quot;&quot;
826 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
827 If Not ScriptForge.SF_Utils._Validate(Pattern, &quot;Pattern&quot;, V_STRING) Then GoTo Catch
829 Try:
830 bAssert = _Assert(&quot;AssertNotLike&quot;, False, A, Empty, Message, Pattern)
832 Finally:
833 AssertNotLike = bAssert
834 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
835 Exit Function
836 Catch:
837 bAssert = False
838 GoTo Finally
839 End Function &apos; SFUnitTests.SF_UnitTest.AssertNotLike
841 REM -----------------------------------------------------------------------------
842 Public Function AssertNotNothing(Optional ByRef A As Variant _
843 , Optional ByVal Message As Variant _
844 ) As Boolean
845 &apos;&apos;&apos; Returns True except when A is an object that has the Nothing value
847 Dim bAssert As Boolean &apos; Return value
848 Const cstThisSub = &quot;UnitTest.AssertNotNothing&quot;
849 Const cstSubArgs = &quot;A, [Message=&quot;&quot;&quot;&quot;]&quot;
851 Check:
852 If IsMissing(A) Then A = Empty
853 If IsMissing(Message) Then Message = &quot;&quot;
854 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
856 Try:
857 bAssert = _Assert(&quot;AssertNotNothing&quot;, False, A, Empty, Message)
859 Finally:
860 AssertNotNothing = bAssert
861 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
862 Exit Function
863 End Function &apos; SFUnitTests.SF_UnitTest.AssertNotNothing
865 REM -----------------------------------------------------------------------------
866 Public Function AssertNotNull(Optional ByRef A As Variant _
867 , Optional ByVal Message As Variant _
868 ) As Boolean
869 &apos;&apos;&apos; Returns True except when A has the Null value
871 Dim bAssert As Boolean &apos; Return value
872 Const cstThisSub = &quot;UnitTest.AssertNotNull&quot;
873 Const cstSubArgs = &quot;A, [Message=&quot;&quot;&quot;&quot;]&quot;
875 Check:
876 If IsMissing(A) Then A = Empty
877 If IsMissing(Message) Then Message = &quot;&quot;
878 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
880 Try:
881 bAssert = _Assert(&quot;AssertNotNull&quot;, False, A, Empty, Message)
883 Finally:
884 AssertNotNull = bAssert
885 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
886 Exit Function
887 End Function &apos; SFUnitTests.SF_UnitTest.AssertNotNull
889 REM -----------------------------------------------------------------------------
890 Public Function AssertNotRegex(Optional ByRef A As Variant _
891 , Optional ByRef Regex As Variant _
892 , Optional ByVal Message As Variant _
893 ) As Boolean
894 &apos;&apos;&apos; Returns True when A is not a string or does not match the given regular expression.
895 &apos;&apos;&apos; The comparison is case-sensitive.
897 Dim bAssert As Boolean &apos; Return value
898 Const cstThisSub = &quot;UnitTest.AssertNotRegex&quot;
899 Const cstSubArgs = &quot;A, Regex, [Message=&quot;&quot;&quot;&quot;]&quot;
901 Check:
902 If IsMissing(A) Then A = Empty
903 If IsMissing(Regex) Then Regex = &quot;&quot;
904 If IsMissing(Message) Then Message = &quot;&quot;
905 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
906 If Not ScriptForge.SF_Utils._Validate(Regex, &quot;Regex&quot;, V_STRING) Then GoTo Catch
908 Try:
909 bAssert = _Assert(&quot;AssertNotRegex&quot;, False, A, Empty, Message, Regex)
911 Finally:
912 AssertNotRegex = bAssert
913 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
914 Exit Function
915 Catch:
916 bAssert = False
917 GoTo Finally
918 End Function &apos; SFUnitTests.SF_UnitTest.AssertNotRegex
920 REM -----------------------------------------------------------------------------
921 Public Function AssertRegex(Optional ByRef A As Variant _
922 , Optional ByRef Regex As Variant _
923 , Optional ByVal Message As Variant _
924 ) As Boolean
925 &apos;&apos;&apos; Returns True when string A matches the given regular expression.
926 &apos;&apos;&apos; The comparison is case-sensitive.
928 Dim bAssert As Boolean &apos; Return value
929 Const cstThisSub = &quot;UnitTest.AssertRegex&quot;
930 Const cstSubArgs = &quot;A, Regex, [Message=&quot;&quot;&quot;&quot;]&quot;
932 Check:
933 If IsMissing(A) Then A = Empty
934 If IsMissing(Regex) Then Regex = &quot;&quot;
935 If IsMissing(Message) Then Message = &quot;&quot;
936 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
937 If Not ScriptForge.SF_Utils._Validate(Regex, &quot;Regex&quot;, V_STRING) Then GoTo Catch
939 Try:
940 bAssert = _Assert(&quot;AssertRegex&quot;, True, A, Empty, Message, Regex)
942 Finally:
943 AssertRegex = bAssert
944 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
945 Exit Function
946 Catch:
947 bAssert = False
948 GoTo Finally
949 End Function &apos; SFUnitTests.SF_UnitTest.AssertRegex
951 REM -----------------------------------------------------------------------------
952 Public Function AssertTrue(Optional ByRef A As Variant _
953 , Optional ByVal Message As Variant _
954 ) As Boolean
955 &apos;&apos;&apos; Returns True when A is a Boolean and its value is True
957 Dim bAssert As Boolean &apos; Return value
958 Const cstThisSub = &quot;UnitTest.AssertTrue&quot;
959 Const cstSubArgs = &quot;A, [Message=&quot;&quot;&quot;&quot;]&quot;
961 Check:
962 If IsMissing(A) Then A = Empty
963 If IsMissing(Message) Then Message = &quot;&quot;
964 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
966 Try:
967 bAssert = _Assert(&quot;AssertTrue&quot;, True, A, Empty, Message)
969 Finally:
970 AssertTrue = bAssert
971 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
972 Exit Function
973 End Function &apos; SFUnitTests.SF_UnitTest.AssertTrue
975 REM -----------------------------------------------------------------------------
976 Public Sub Fail(Optional ByVal Message As Variant)
977 &apos;&apos;&apos; Forces a test failure
979 Dim bAssert As Boolean &apos; Fictive return value
980 Const cstThisSub = &quot;UnitTest.Fail&quot;
981 Const cstSubArgs = &quot;[Message=&quot;&quot;&quot;&quot;]&quot;
983 Check:
984 If IsMissing(Message) Then Message = &quot;&quot;
985 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
987 Try:
988 bAssert = _Assert(&quot;Fail&quot;, False, Empty, Empty, Message)
990 Finally:
991 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
992 Exit Sub
993 End Sub &apos; SFUnitTests.SF_UnitTest.Fail
995 REM -----------------------------------------------------------------------------
996 Public Sub Log(Optional ByVal Message As Variant)
997 &apos;&apos;&apos; Records the given message in the test report (console)
999 Dim bAssert As Boolean &apos; Fictive return value
1000 Dim bVerbose As Boolean : bVerbose = _Verbose
1001 Const cstThisSub = &quot;UnitTest.Log&quot;
1002 Const cstSubArgs = &quot;[Message=&quot;&quot;&quot;&quot;]&quot;
1004 Check:
1005 If IsMissing(Message) Then Message = &quot;&quot;
1006 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
1008 Try:
1009 &apos; Force the display of the message in the console
1010 _Verbose = True
1011 bAssert = _Assert(&quot;Log&quot;, True, Empty, Empty, Message)
1012 _Verbose = bVerbose
1014 Finally:
1015 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
1016 Exit Sub
1017 End Sub &apos; SFUnitTests.SF_UnitTest.Log
1019 REM -----------------------------------------------------------------------------
1020 Public Function GetProperty(Optional ByVal PropertyName As Variant) As Variant
1021 &apos;&apos;&apos; Return the actual value of the given property
1022 &apos;&apos;&apos; Args:
1023 &apos;&apos;&apos; PropertyName: the name of the property as a string
1024 &apos;&apos;&apos; Returns:
1025 &apos;&apos;&apos; The actual value of the property
1026 &apos;&apos;&apos; Exceptions
1027 &apos;&apos;&apos; ARGUMENTERROR The property does not exist
1028 &apos;&apos;&apos; Examples:
1029 &apos;&apos;&apos; myUnitTest.GetProperty(&quot;Duration&quot;)
1031 Const cstThisSub = &quot;UnitTest.GetProperty&quot;
1032 Const cstSubArgs = &quot;PropertyName&quot;
1034 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
1035 GetProperty = Null
1037 Check:
1038 If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
1039 If Not ScriptForge.SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
1040 End If
1042 Try:
1043 GetProperty = _PropertyGet(PropertyName)
1045 Finally:
1046 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
1047 Exit Function
1048 Catch:
1049 GoTo Finally
1050 End Function &apos; SFUnitTests.SF_UnitTest.Properties
1052 REM -----------------------------------------------------------------------------
1053 Public Function Methods() As Variant
1054 &apos;&apos;&apos; Return the list or methods of the UnitTest class as an array
1056 Methods = Array( _
1057 &quot;AssertAlmostEqual&quot; _
1058 , &quot;AssertEqual&quot; _
1059 , &quot;AssertFalse&quot; _
1060 , &quot;AssertGreater&quot; _
1061 , &quot;AssertGreaterEqual&quot; _
1062 , &quot;AssertIn&quot; _
1063 , &quot;AssertIsInstance&quot; _
1064 , &quot;AssertIsNothing&quot; _
1065 , &quot;AssertLike&quot; _
1066 , &quot;AssertNotRegex&quot; _
1067 , &quot;AssertIsNull&quot; _
1068 , &quot;AssertLess&quot; _
1069 , &quot;AssertLessEqual&quot; _
1070 , &quot;AssertNotAlmostEqual&quot; _
1071 , &quot;AssertNotEqual&quot; _
1072 , &quot;AssertNotIn&quot; _
1073 , &quot;AssertNotInstance&quot; _
1074 , &quot;AssertNotLike&quot; _
1075 , &quot;AssertNotNothing&quot; _
1076 , &quot;AssertNotNull&quot; _
1077 , &quot;AssertRegex&quot; _
1078 , &quot;AssertTrue&quot; _
1079 , &quot;Fail&quot; _
1080 , &quot;Log&quot; _
1081 , &quot;RunTest&quot; _
1082 , &quot;SkipTest&quot; _
1085 End Function &apos; SFUnitTests.SF_UnitTest.Methods
1087 REM -----------------------------------------------------------------------------
1088 Public Function Properties() As Variant
1089 &apos;&apos;&apos; Return the list or properties of the UnitTest class as an array
1091 Properties = Array( _
1092 &quot;LongMessage&quot; _
1093 , &quot;ReturnCode&quot; _
1094 , &quot;Verbose&quot; _
1095 , &quot;WhenAssertionFails&quot; _
1098 End Function &apos; SFUnitTests.SF_UnitTest.Properties
1100 REM -----------------------------------------------------------------------------
1101 Public Sub ReportError(Optional ByVal Message As Variant)
1102 &apos;&apos;&apos; DIsplay a message box with the current property values of the &quot;Exception&quot; service.
1103 &apos;&apos;&apos; Depending on the WhenAssertionFails property, a Raise() or RaiseWarning()
1104 &apos;&apos;&apos; is issued. The Raise() method stops completely the Basic running process.
1105 &apos;&apos;&apos; The ReportError() method is presumed present in a user script in an error
1106 &apos;&apos;&apos; handling part of the actual testcase.
1107 &apos;&apos;&apos; Args:
1108 &apos;&apos;&apos; Message: a string to replace or to complete the standard message description
1109 &apos;&apos;&apos; Example:
1110 &apos;&apos;&apos; See the Test_ArraySize() sub in the module&apos;s heading example
1112 Dim sLine As String &apos; Line number where the error occurred
1113 Dim sError As String &apos; Exception description
1114 Dim sErrorCode As String &apos; Exception number
1115 Const cstThisSub = &quot;UnitTest.ReportError&quot;
1116 Const cstSubArgs = &quot;[Message=&quot;&quot;&quot;&quot;]&quot;
1118 Check:
1119 If IsMissing(Message) Or IsEmpty(Message) Then Message = &quot;&quot;
1120 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
1121 If VarType(Message) &lt;&gt; V_STRING Then Message = &quot;&quot;
1123 Try:
1124 sLine = &quot;ln &quot; &amp; CStr(Exception.Source)
1125 If _ExecutionMode = FULLMODE Then sLine = _Module &amp; &quot;.&quot; &amp; _TestCase &amp; &quot; &quot; &amp; sLine
1126 If Len(Message) &gt; 0 Then
1127 sError = Message
1128 Else
1129 If Exception.Number = INVALIDPROCEDURECALL Then
1130 sError = &quot;Test case failure&quot;
1131 sErrorCode = &quot;ASSERTIONFAILED&quot;
1132 Else
1133 sError = Exception.Description
1134 sErrorCode = CStr(Exception.Number)
1135 End If
1136 End If
1138 Select Case _WhenAssertionFails
1139 Case FAILIGNORE
1140 Case FAILSTOPSUITE
1141 Exception.RaiseWarning(sErrorCode, sLine, sError)
1142 Case FAILIMMEDIATESTOP
1143 Exception.Raise(sErrorCode, sLine, sError)
1144 End Select
1146 Finally:
1147 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
1148 Exit Sub
1149 End Sub &apos; SFUnitTests.SF_UnitTest.ReportError
1150 REM -----------------------------------------------------------------------------
1151 Public Function RunTest(Optional ByVal TestSuite As Variant _
1152 , Optional ByVal TestCasePattern As Variant _
1153 , Optional ByVal Message As Variant _
1154 ) As Integer
1155 &apos;&apos;&apos; Execute a test suite pointed out by a module name.
1156 &apos;&apos;&apos; Each test case will be run independently from each other.
1157 &apos;&apos;&apos; The names of the test cases to be run may be selected with a string pattern.
1158 &apos;&apos;&apos; The test is &quot;orchestrated&quot; by this method:
1159 &apos;&apos;&apos; 1. Execute the optional Setup() method present in the module
1160 &apos;&apos;&apos; 2. Execute once each test case, in any order
1161 &apos;&apos;&apos; 3, Execute the optional TearDown() method present in the module
1162 &apos;&apos;&apos; Args:
1163 &apos;&apos;&apos; TestSuite: the name of the module containing the set of test cases to run
1164 &apos;&apos;&apos; TestCasePattern: the pattern that the test cases must match. The comparison is not case-sensitive.
1165 &apos;&apos;&apos; Non-matching functions and subs are ignored.
1166 &apos;&apos;&apos; Admitted wildcard are: the &quot;?&quot; represents any single character
1167 &apos;&apos;&apos; the &quot;*&quot; represents zero, one, or multiple characters
1168 &apos;&apos;&apos; The default pattern is &quot;Test_*&quot;
1169 &apos;&apos;&apos; Message: the message to be displayed in the console when the test starts.
1170 &apos;&apos;&apos; Returns:
1171 &apos;&apos;&apos; One of the return codes of the execution (RCxxx constants)
1172 &apos;&apos;&apos; Examples:
1173 &apos;&apos;&apos; GlobalScope.BasicLibraries.loadLibrary(&quot;ScriptForge&quot;)
1174 &apos;&apos;&apos; Dim test : test = CreateScriptService(&quot;UnitTest&quot;, ThisComponent, &quot;Tests&quot;)
1175 &apos;&apos;&apos; test.RunTest(&quot;AllTests&quot;) &apos; AllTests is a module name ; test cases are named &quot;Test_*&quot; (default)
1177 Dim iRun As Integer &apos; Return value
1178 Dim sRunMessage As String &apos; Reporting
1179 Dim iModule As Integer &apos; Index of module currently running
1180 Dim vMethods As Variant &apos; Set of methods
1181 Dim sMethod As String &apos; A single method
1182 Dim iMethod As Integer &apos; Index in MethodNames
1183 Dim m As Integer
1185 Const cstThisSub = &quot;UnitTest.RunTest&quot;
1186 Const cstSubArgs = &quot;TestSuite, [TestCasePattern=&quot;&quot;Test_*&quot;&quot;], [Message=&quot;&quot;&quot;&quot;]&quot;
1188 iRun = RCNORMALEND
1189 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
1191 Check:
1192 If IsMissing(TestCasePattern) Or IsEmpty(TestCasePattern) Then TestCasePattern = &quot;Test_*&quot;
1193 If IsMissing(Message) Or IsEmpty(Message) Then Message = &quot;&quot;
1194 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
1195 If Not ScriptForge.SF_Utils._Validate(TestSuite, &quot;TestSuite&quot;, V_STRING, ModuleNames) Then GoTo Catch
1196 If Not ScriptForge.SF_Utils._Validate(TestCasePattern, &quot;TestCasePattern&quot;, V_STRING) Then GoTo Catch
1197 If Not ScriptForge.SF_Utils._Validate(Message, &quot;Message&quot;, V_STRING) Then GoTo Catch
1199 &apos; A RunTest() is forbidden inside a test suite or when simple mode
1200 If _Status &lt;&gt; STATUSSTANDBY Or _ExecutionMode &lt;&gt; FULLMODE Then GoTo CatchMethod
1202 &apos; Ignore any call when an abnormal end has been encountered
1203 If _ReturnCode = RCABORTTEST Then GoTo Catch
1205 Try:
1206 iModule = ScriptForge.SF_Array.IndexOf(ModuleNames, TestSuite, CaseSensitive := False, SortOrder := &quot;ASC&quot;)
1207 _Module = ModuleNames(iModule)
1209 &apos; Start timer
1210 If Not IsNull(SuiteTimer) Then SuiteTimer = SuiteTimer.Dispose()
1211 Set SuiteTimer = CreateScriptService(&quot;ScriptForge.Timer&quot;, True)
1213 &apos; Report the start of a new test suite
1214 sRunMessage = &quot;RUNTEST ENTER testsuite=&apos;&quot; &amp; LibraryName &amp; &quot;.&quot; &amp; _Module &amp; &quot;&apos;, pattern=&apos;&quot; &amp; TestCasePattern &amp; &quot;&apos;&quot;
1215 _ReportMessage(sRunMessage, Message)
1216 _Status = STATUSSUITESTARTED
1218 &apos; Collect all the methods of the module
1219 If Modules(iModule).hasChildNodes() Then
1220 vMethods = Modules(iModule).getChildNodes()
1221 MethodNames = Array()
1222 For m = 0 To UBound(vMethods)
1223 sMethod = vMethods(m).getName()
1224 MethodNames = ScriptForge.SF_Array.Append(MethodNames, sMethod)
1225 Next m
1226 End If
1228 &apos; Execute the Setup() method, if it exists
1229 iMethod = ScriptForge.SF_Array.IndexOf(MethodNames, &quot;Setup&quot;, CaseSensitive := False, SortOrder := &quot;ASC&quot;)
1230 If iMethod &gt;= 0 Then
1231 _TestCase = MethodNames(iMethod) &apos; _TestCase is used in ReportError()
1232 If Not _ExecuteScript(_TestCase) Then GoTo Catch
1233 End If
1235 &apos; Execute the test cases that match the pattern
1236 For iMethod = 0 To UBound(MethodNames)
1237 If _ReturnCode = RCSKIPTEST Or _ReturnCode = RCASSERTIONFAILED Then Exit For
1238 sMethod = MethodNames(iMethod)
1239 If ScriptForge.SF_String.IsLike(sMethod, TestCasePattern, CaseSensitive := False) Then
1240 _TestCase = sMethod
1241 &apos; Start timer
1242 If Not IsNull(CaseTimer) Then CaseTimer = CaseTimer.Dispose()
1243 Set CaseTimer = CreateScriptService(&quot;ScriptForge.Timer&quot;, True)
1244 If Not _ExecuteScript(sMethod) Then GoTo Catch
1245 CaseTimer.Terminate()
1246 _TestCase = &quot;&quot;
1247 End If
1248 Next iMethod
1250 If _ReturnCode &lt;&gt; RCSKIPTEST Then
1251 &apos; Execute the TearDown() method, if it exists
1252 iMethod = ScriptForge.SF_Array.IndexOf(MethodNames, &quot;TearDown&quot;, CaseSensitive := False, SortOrder := &quot;ASC&quot;)
1253 If iMethod &gt;= 0 Then
1254 _TestCase = MethodNames(iMethod) &apos; _TestCase is used in ReportError()
1255 If Not _ExecuteScript(_TestCase) Then GoTo Catch
1256 End If
1257 End If
1259 &apos; Report the end of the current test suite
1260 sRunMessage = &quot;RUNTEST EXIT testsuite=&apos;&quot; &amp; LibraryName &amp; &quot;.&quot; &amp; _Module &amp; &quot;&apos; &quot; &amp; _Duration(&quot;Suite&quot;, True)
1261 _ReportMessage(sRunMessage, Message)
1263 &apos; Stop timer
1264 SuiteTimer.Terminate()
1266 &apos; Housekeeping
1267 MethodNames = Array()
1268 _Module = &quot;&quot;
1269 _Status = STATUSSTANDBY
1271 Finally:
1272 _ReturnCode = iRun
1273 RunTest = iRun
1274 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
1275 Exit Function
1276 Catch:
1277 iRun = RCABORTTEST
1278 GoTo Finally
1279 CatchMethod:
1280 ScriptForge.SF_Exception.RaiseFatal(UNITTESTMETHODERROR, &quot;RunTest&quot;)
1281 GoTo Catch
1282 End Function &apos; SFUnitTests.SF_UnitTest.RunTest
1284 REM -----------------------------------------------------------------------------
1285 Public Function SetProperty(Optional ByVal PropertyName As Variant _
1286 , Optional ByRef Value As Variant _
1287 ) As Boolean
1288 &apos;&apos;&apos; Set a new value to the given property
1289 &apos;&apos;&apos; Args:
1290 &apos;&apos;&apos; PropertyName: the name of the property as a string
1291 &apos;&apos;&apos; Value: its new value
1292 &apos;&apos;&apos; Exceptions
1293 &apos;&apos;&apos; ARGUMENTERROR The property does not exist
1295 Const cstThisSub = &quot;UnitTest.SetProperty&quot;
1296 Const cstSubArgs = &quot;PropertyName, Value&quot;
1298 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
1299 SetProperty = False
1301 Check:
1302 If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
1303 If Not ScriptForge.SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
1304 End If
1306 Try:
1307 SetProperty = _PropertySet(PropertyName, Value)
1309 Finally:
1310 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
1311 Exit Function
1312 Catch:
1313 GoTo Finally
1314 End Function &apos; SFUnitTests.SF_UnitTest.SetProperty
1316 REM -----------------------------------------------------------------------------
1317 Public Function SkipTest(Optional ByVal Message As Variant) As Boolean
1318 &apos;&apos;&apos; Interrupt the running test suite. The TearDown() method is NOT executed.
1319 &apos;&apos;&apos; The SkipTest() method is normally meaningful only in a Setup() method when not all the
1320 &apos;&apos;&apos; conditions to run the test are met.
1321 &apos;&apos;&apos; It is up to the Setup() script to exit shortly after the SkipTest() call..
1322 &apos;&apos;&apos; The method may also be executed in a test case. Next test cases will not be executed.
1323 &apos;&apos;&apos; Remember however that the test cases are executed is an arbitrary order.
1324 &apos;&apos;&apos; Args:
1325 &apos;&apos;&apos; Message: the message to be displayed in the console
1326 &apos;&apos;&apos; Returns:
1327 &apos;&apos;&apos; True when successful
1328 &apos;&apos;&apos; Examples:
1329 &apos;&apos;&apos; GlobalScope.BasicLibraries.loadLibrary(&quot;ScriptForge&quot;)
1330 &apos;&apos;&apos; Dim test : test = CreateScriptService(&quot;UnitTest&quot;, ThisComponent, &quot;Tests&quot;)
1331 &apos;&apos;&apos; test.SkipTest(&quot;AllTests&quot;) &apos; AllTests is a module name ; test cases are named &quot;Test_*&quot; (default)
1333 Dim bSkip As Boolean &apos; Return value
1334 Dim sSkipMessage As String &apos; Reporting
1336 Const cstThisSub = &quot;UnitTest.SkipTest&quot;
1337 Const cstSubArgs = &quot;[Message=&quot;&quot;&quot;&quot;]&quot;
1339 bSkip = False
1340 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
1342 Check:
1343 If IsMissing(Message) Or IsEmpty(Message) Then Message = &quot;&quot;
1344 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Unconditional !
1345 If Not ScriptForge.SF_Utils._Validate(Message, &quot;Message&quot;, V_STRING) Then GoTo Catch
1347 &apos; A SkipTest() is forbidden when simple mode
1348 If _ExecutionMode &lt;&gt; FULLMODE Then GoTo CatchMethod
1350 &apos; Ignore any call when an abnormal end has been encountered
1351 If _ReturnCode = RCABORTTEST Then GoTo Catch
1353 Try:
1354 If _Status = STATUSSETUP Or _Status = STATUSTESTCASE Then
1355 _ReturnCode = RCSKIPTEST
1356 bSkip = True
1357 &apos; Exit message
1358 sSkipMessage = &quot; SKIPTEST testsuite=&apos;&quot; &amp; LibraryName &amp; &quot;.&quot; &amp; _Module &amp; &quot;&apos; &quot; &amp; _Duration(&quot;Suite&quot;, True)
1359 _ReportMessage(sSkipMessage, Message)
1360 End If
1362 Finally:
1363 SkipTest = bSkip
1364 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
1365 Exit Function
1366 Catch:
1367 _ReturnCode = RCABORTTEST
1368 GoTo Finally
1369 CatchMethod:
1370 ScriptForge.SF_Exception.RaiseFatal(UNITTESTMETHODERROR, &quot;SkipTest&quot;)
1371 GoTo Catch
1372 End Function &apos; SFUnitTests.SF_UnitTest.SkipTest
1374 REM =========================================================== PRIVATE FUNCTIONS
1376 REM -----------------------------------------------------------------------------
1377 Private Function _Assert(ByVal psAssert As String _
1378 , ByVal pvReturn As Variant _
1379 , ByRef A As Variant _
1380 , ByRef B As Variant _
1381 , Optional ByVal pvMessage As Variant _
1382 , Optional ByVal pvArg As Variant _
1383 ) As Boolean
1384 &apos;&apos;&apos; Evaluation of the assertion and management of the success or the failure
1385 &apos;&apos;&apos; Args:
1386 &apos;&apos;&apos; psAssert: the assertion verb as a string
1387 &apos;&apos;&apos; pvReturn: may be True, False or Empty
1388 &apos;&apos;&apos; When True (resp. False), the assertion must be evaluated as True (resp. False)
1389 &apos;&apos;&apos; e.g. AssertEqual() will call _Assert(&quot;AssertEqual&quot;, True, ...)
1390 &apos;&apos;&apos; AssertNotEqual() will call _Assert(&quot;AssertNotEqual&quot;, False, ...)
1391 &apos;&apos;&apos; Empty may be used for recursive calls of the function (for comparing arrays, ...)
1392 &apos;&apos;&apos; A: always present
1393 &apos;&apos;&apos; B: may be empty
1394 &apos;&apos;&apos; pvMessage: the message to display on the console
1395 &apos;&apos;&apos; pvArg: optional additional argument of the assert function
1396 &apos;&apos;&apos; Returns:
1397 &apos;&apos;&apos; True when success
1399 Dim bAssert As Boolean &apos; Return value
1400 Dim bEval As Boolean &apos; To be compared with pvReturn
1401 Dim iVarTypeA As Integer &apos; Alias of _VarTypeExt(A)
1402 Dim iVarTypeB As Integer &apos; Alias of _VarTypeExt(B)
1403 Dim oVarTypeObjA As Object &apos; SF_Utils.ObjectDescriptor
1404 Dim oVarTypeObjB As Object &apos; SF_Utils.ObjectDescriptor
1405 Dim oUtils As Object : Set oUtils = ScriptForge.SF_Utils
1406 Dim iDims As Integer &apos; Number of dimensions of array
1407 Dim oAliasB As Object &apos; Alias of B to bypass the &quot;Object variable not set&quot; issue
1408 Dim dblA As Double &apos; Alias of A
1409 Dim dblB As Double &apos; Alias of B
1410 Dim dblTolerance As Double &apos; Alias of pvArg
1411 Dim oString As Object : Set oString = ScriptForge.SF_String
1412 Dim sArgName As String &apos; Argument description
1413 Dim i As Long, j As Long
1415 Check:
1416 bAssert = False
1417 If IsMissing(pvMessage) Then pvMessage = &quot;&quot;
1418 If Not oUtils._Validate(pvMessage, &quot;Message&quot;, V_STRING) Then GoTo Finally
1419 If IsMissing(pvArg) Then pvArg = &quot;&quot;
1421 Try:
1422 iVarTypeA = oUtils._VarTypeExt(A)
1423 iVarTypeB = oUtils._VarTypeExt(B)
1424 sArgName = &quot;&quot;
1426 Select Case UCase(psAssert)
1427 Case UCase(&quot;AssertAlmostEqual&quot;), UCase(&quot;AssertNotAlmostEqual&quot;)
1428 bEval = ( iVarTypeA = iVarTypeB And iVarTypeA = ScriptForge.V_NUMERIC )
1429 If bEval Then
1430 dblA = CDbl(A)
1431 dblB = CDbl(B)
1432 dblTolerance = Abs(CDbl(pvArg))
1433 bEval = ( Abs(dblA - dblB) &lt;= (dblTolerance * Iif(Abs(dblA) &gt; Abs(DblB), Abs(dblA), Abs(dblB))) )
1434 End If
1435 Case UCase(&quot;AssertEqual&quot;), UCase(&quot;AssertNotEqual&quot;)
1436 If Not IsArray(A) Then
1437 bEval = ( iVarTypeA = iVarTypeB )
1438 If bEval Then
1439 Select Case iVarTypeA
1440 Case V_EMPTY, V_NULL
1441 Case V_STRING
1442 bEval = ( StrComp(A, B, 1) = 0 )
1443 Case ScriptForge.V_NUMERIC, ScriptForge.V_BOOLEAN
1444 bEval = ( A = B )
1445 Case V_DATE
1446 bEval = ( Abs(DateDiff(&quot;s&quot;, A, B)) = 0 )
1447 Case ScriptForge.V_OBJECT
1448 Set oVarTypeObjA = oUtils._VarTypeObj(A)
1449 Set oVarTypeObjB = oUtils._VarTypeObj(B)
1450 bEval = ( oVarTypeObjA.iVarType = oVarTypeObjB.iVarType )
1451 If bEval Then
1452 Select Case oVarTypeObjA.iVarType
1453 Case ScriptForge.V_NOTHING
1454 Case ScriptForge.V_UNOOBJECT
1455 bEval = EqualUnoObjects(A, B)
1456 Case ScriptForge.V_SFOBJECT, ScriptForge.V_BASICOBJECT
1457 bEval = False
1458 End Select
1459 End If
1460 End Select
1461 End If
1462 Else &apos; Compare arrays
1463 bEval = IsArray(B)
1464 If bEval Then
1465 iDims = ScriptForge.SF_Array.CountDims(A)
1466 bEval = ( iDims = ScriptForge.SF_Array.CountDims(B) And iDims &lt;= 2 )
1467 If bEval Then
1468 Select Case iDims
1469 Case -1, 0 &apos; Scalars (not possible) or empty arrays
1470 Case 1 &apos; 1D array
1471 bEval = ( LBound(A) = LBound(B) And UBound(A) = UBound(B) )
1472 If bEval Then
1473 For i = LBound(A) To UBound(A)
1474 bEval = _Assert(psAssert, Empty, A(i), B(i))
1475 If Not bEval Then Exit For
1476 Next i
1477 End If
1478 Case 2 &apos; 2D array
1479 bEval = ( LBound(A, 1) = LBound(B, 1) And UBound(A, 1) = UBound(B, 1) _
1480 And LBound(A, 2) = LBound(B, 2) And UBound(A, 2) = UBound(B, 2) )
1481 If bEval Then
1482 For i = LBound(A, 1) To UBound(A, 1)
1483 For j = LBound(A, 2) To UBound(A, 2)
1484 bEval = _Assert(psAssert, Empty, A(i, j), B(i, j))
1485 If Not bEval Then Exit For
1486 Next j
1487 If Not bEval Then Exit For
1488 Next i
1489 End If
1490 End Select
1491 End If
1492 End If
1493 End If
1494 Case UCase(&quot;AssertFalse&quot;)
1495 If iVarTypeA = ScriptForge.V_BOOLEAN Then bEval = Not A Else bEval = False
1496 Case UCase(&quot;AssertGreater&quot;), UCase(&quot;AssertLessEqual&quot;)
1497 bEval = ( iVarTypeA = iVarTypeB _
1498 And (iVarTypeA = ScriptForge.V_NUMERIC Or iVarTypeA = V_STRING Or iVarTypeA = V_DATE) )
1499 If bEval Then bEval = ( A &gt; B )
1500 Case UCase(&quot;AssertGreaterEqual&quot;), UCase(&quot;AssertLess&quot;)
1501 bEval = ( iVarTypeA = iVarTypeB _
1502 And (iVarTypeA = ScriptForge.V_NUMERIC Or iVarTypeA = V_STRING Or iVarTypeA = V_DATE) )
1503 If bEval Then bEval = ( A &gt;= B )
1504 Case UCase(&quot;AssertIn&quot;), UCase(&quot;AssertNotIn&quot;)
1505 Set oVarTypeObjB = oUtils._VarTypeObj(B)
1506 Select Case True
1507 Case iVarTypeA = V_STRING And iVarTypeB = V_STRING
1508 bEval = ( Len(A) &gt; 0 And Len(B) &gt; 0 )
1509 If bEval Then bEval = ( InStr(1, B, A, 0) &gt; 0 )
1510 Case (iVarTypeA = V_DATE Or iVarTypeA = V_STRING Or iVarTypeA = ScriptForge.V_NUMERIC) _
1511 And iVarTypeB &gt;= ScriptForge.V_ARRAY
1512 bEval = ( ScriptForge.SF_Array.CountDims(B) = 1 )
1513 If bEval Then bEval = ScriptForge.SF_Array.Contains(B, A, CaseSensitive := True)
1514 Case oVarTypeObjB.iVarType = ScriptForge.V_SFOBJECT And oVarTypeObjB.sObjectType = &quot;DICTIONARY&quot;
1515 bEval = ( Len(A) &gt; 0 )
1516 If bEval Then
1517 Set oAliasB = B
1518 bEval = ScriptForge.SF_Array.Contains(oAliasB.Keys(), A, CaseSensitive := True)
1519 End If
1520 Case Else
1521 bEval = False
1522 End Select
1523 Case UCase(&quot;AssertIsInstance&quot;), UCase(&quot;AssertNotInstance&quot;)
1524 Set oVarTypeObjA = oUtils._VarTypeObj(A)
1525 sArgName = &quot;ObjectType&quot;
1526 With oVarTypeObjA
1527 Select Case .iVarType
1528 Case ScriptForge.V_UNOOBJECT
1529 bEval = ( pvArg = .sObjectType )
1530 Case ScriptForge.V_SFOBJECT
1531 bEval = ( UCase(pvArg) = UCase(.sObjectType) Or UCase(pvArg) = &quot;SF_&quot; &amp; UCase(.sObjectType) _
1532 Or UCase(pvArg) = UCase(.sServiceName) )
1533 Case ScriptForge.V_NOTHING, ScriptForge.V_BASICOBJECT
1534 bEval = False
1535 Case &gt;= ScriptForge.V_ARRAY
1536 bEval = ( UCase(pvArg) = &quot;ARRAY&quot; )
1537 Case Else
1538 bEval = ( UCase(TypeName(A)) = UCase(pvArg) )
1539 End Select
1540 End With
1541 Case UCase(&quot;AssertIsNothing&quot;), UCase(&quot;AssertNotNothing&quot;)
1542 bEval = ( iVarTypeA = ScriptForge.V_OBJECT )
1543 If bEval Then bEval = ( A Is Nothing )
1544 Case UCase(&quot;AssertIsNull&quot;), UCase(&quot;AssertNotNull&quot;)
1545 bEval = ( iVarTypeA = V_NULL )
1546 Case UCase(&quot;AssertLike&quot;), UCase(&quot;AssertNotLike&quot;)
1547 sArgName = &quot;Pattern&quot;
1548 bEval = ( iVarTypeA = V_STRING And Len(pvArg) &gt; 0 )
1549 If bEval Then bEval = oString.IsLike(A, pvArg, CaseSensitive := True)
1550 Case UCase(&quot;AssertRegex&quot;), UCase(&quot;AssertNotRegex&quot;)
1551 sArgName = &quot;Regex&quot;
1552 bEval = ( iVarTypeA = V_STRING And Len(pvArg) &gt; 0 )
1553 If bEval Then bEval = oString.IsRegex(A, pvArg, CaseSensitive := True)
1554 Case UCase(&quot;AssertTrue&quot;)
1555 If iVarTypeA = ScriptForge.V_BOOLEAN Then bEval = A Else bEval = False
1556 Case UCase(&quot;FAIL&quot;), UCase(&quot;Log&quot;)
1557 bEval = True
1558 Case Else
1559 End Select
1561 &apos; Check the result of the assertion vs. what it should be
1562 If IsEmpty(pvReturn) Then
1563 bAssert = bEval &apos; Recursive call =&gt; Reporting and failure management are done by calling _Assert() procedure
1564 Else &apos; pvReturn is Boolean =&gt; Call from user script
1565 bAssert = Iif(pvReturn, bEval, Not bEval)
1566 &apos; Report the assertion evaluation
1567 If _Verbose Or Not bAssert Then
1568 _ReportMessage(&quot; &quot; &amp; psAssert _
1569 &amp; Iif(IsEmpty(A), &quot;&quot;, &quot; = &quot; &amp; bAssert &amp; &quot;, A = &quot; &amp; oUtils._Repr(A)) _
1570 &amp; Iif(IsEmpty(B), &quot;&quot;, &quot;, B = &quot; &amp; oUtils._Repr(B)) _
1571 &amp; Iif(Len(sArgName) = 0, &quot;&quot;, &quot;, &quot; &amp; sArgName &amp; &quot; = &quot; &amp; pvArg) _
1572 , pvMessage)
1573 End If
1574 &apos; Manage assertion failure
1575 If Not bAssert Then
1576 _FailedAssert = psAssert
1577 Select Case _WhenAssertionFails
1578 Case FAILIGNORE &apos; Do nothing
1579 Case Else
1580 _ReturnCode = RCASSERTIONFAILED
1581 &apos; Cause artificially a run-time error
1582 Dim STRINGBADUSE As String
1584 &apos;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1585 &apos;+ To avoid a run-time error on next executable statement, +
1586 &apos;+ insert an error handler in the code of your test case: +
1587 &apos;+ Like in next code: +
1588 &apos;+ On Local Error GoTo Catch +
1589 &apos;+ ... +
1590 &apos;+ Catch: +
1591 &apos;+ myTest.ReportError() +
1592 &apos;+ Exit Sub +
1593 &apos;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1595 STRINGBADUSE = Right(&quot;&quot;, -1) &apos; Raises &quot;#5 - Invalid procedure call&quot; error
1597 End Select
1598 End If
1599 End If
1601 Finally:
1602 _Assert = bAssert
1603 Exit Function
1605 End Function &apos; SFUnitTests.SF_UnitTest._Assert
1607 REM -----------------------------------------------------------------------------
1608 Private Function _Duration(ByVal psTimer As String _
1609 , Optional ByVal pvBrackets As Variant _
1610 ) As String
1611 &apos;&apos;&apos; Return the Duration property of the given timer
1612 &apos;&apos;&apos; or the empty string if the timer is undefined or not started
1613 &apos;&apos;&apos; Args:
1614 &apos;&apos;&apos; psTimer: &quot;Test&quot;, &quot;Suite&quot; or &quot;TestCase&quot;
1615 &apos;&apos;&apos; pbBrackets: surround with brackets when True. Default = False
1617 Dim sDuration As String &apos; Return value
1618 Dim oTimer As Object &apos; Alias of psTimer
1620 Check:
1621 If IsMissing(pvBrackets) Or IsEmpty(pvBrackets) Then pvBrackets = False
1623 Try:
1624 Select Case psTimer
1625 Case &quot;Test&quot; : Set oTimer = TestTimer
1626 Case &quot;Suite&quot; : Set oTimer = SuiteTimer
1627 Case &quot;TestCase&quot;, &quot;Case&quot; : Set oTimer = CaseTimer
1628 End Select
1629 If Not IsNull(oTimer) Then
1630 sDuration = CStr(oTimer.Duration) &amp; &quot; &quot;
1631 If pvBrackets Then sDuration = &quot;(&quot; &amp; Trim(sDuration) &amp; &quot; sec)&quot;
1632 Else
1633 sDuration = &quot;&quot;
1634 End If
1636 Finally:
1637 _Duration = sDuration
1638 End Function &apos; SFUnitTests.SF_UnitTest._Duration
1640 REM -----------------------------------------------------------------------------
1641 Private Function _ExecuteScript(psMethod As String) As Boolean
1642 &apos;&apos;&apos; Run the given method and report start and stop
1643 &apos;&apos;&apos; The targeted method is presumed not to return anything (Sub)
1644 &apos;&apos;&apos; Args:
1645 &apos;&apos;&apos; psMethod: the scope, the library and the module are predefined in the instance internals
1646 &apos;&apos;&apos; Returns:
1647 &apos;&apos;&apos; True when successful
1649 Dim bExecute As Boolean &apos; Return value
1650 Dim sRun As String &apos; SETUP, TEARDOWN or TESTCASE
1652 On Local Error GoTo Catch
1653 bExecute = True
1655 Try:
1656 &apos; Set status before the effective execution
1657 sRun = UCase(psMethod)
1658 Select Case UCase(psMethod)
1659 Case &quot;SETUP&quot; : _Status = STATUSSETUP
1660 Case &quot;TEARDOWN&quot; : _Status = STATUSTEARDOWN
1661 Case Else : _Status = STATUSTESTCASE
1662 sRun = &quot;TESTCASE&quot;
1663 End Select
1665 &apos; Report and execute
1666 _ReportMessage(&quot; &quot; &amp; sRun &amp; &quot; &quot; &amp; LibraryName &amp; &quot;.&quot; &amp; _Module &amp; &quot;.&quot; &amp; psMethod &amp; &quot;() ENTER&quot;)
1667 Session.ExecuteBasicScript(Scope, LibraryName &amp; &quot;.&quot; &amp; _Module &amp; &quot;.&quot; &amp; psMethod, [Me])
1668 _ReportMessage(&quot; &quot; &amp; sRun &amp; &quot; &quot; &amp; LibraryName &amp; &quot;.&quot; &amp; _Module &amp; &quot;.&quot; &amp; psMethod &amp; &quot;() EXIT&quot; _
1669 &amp; Iif(_STATUS = STATUSTESTCASE, &quot; &quot; &amp; _Duration(&quot;Case&quot;, True), &quot;&quot;))
1670 &apos; Reset status
1671 _Status = STATUSSUITESTARTED
1673 Finally:
1674 _ExecuteScript = bExecute
1675 Exit Function
1676 Catch:
1677 bExecute = False
1678 _ReturnCode = RCABORTTEST
1679 GoTo Finally
1680 End Function &apos; SFUnitTests.SF_UnitTest._ExecuteScript
1682 REM -----------------------------------------------------------------------------
1683 Private Function _PropertyGet(Optional ByVal psProperty As String)
1684 &apos;&apos;&apos; Return the named property
1685 &apos;&apos;&apos; Args:
1686 &apos;&apos;&apos; psProperty: the name of the property
1688 Dim cstThisSub As String
1689 Dim cstSubArgs As String
1691 cstThisSub = &quot;UnitTest.get&quot; &amp; psProperty
1692 cstSubArgs = &quot;&quot;
1693 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
1695 Select Case UCase(psProperty)
1696 Case UCase(&quot;LongMessage&quot;)
1697 _PropertyGet = _LongMessage
1698 Case UCase(&quot;ReturnCode&quot;)
1699 _PropertyGet = _ReturnCode
1700 Case UCase(&quot;Verbose&quot;)
1701 _PropertyGet = _Verbose
1702 Case UCase(&quot;WhenAssertionFails&quot;)
1703 _PropertyGet = _WhenAssertionFails
1704 Case Else
1705 _PropertyGet = Null
1706 End Select
1708 Finally:
1709 SF_Utils._ExitFunction(cstThisSub)
1710 Exit Function
1711 End Function &apos; SFUnitTests.SF_UnitTest._PropertyGet
1713 REM -----------------------------------------------------------------------------
1714 Private Function _PropertySet(Optional ByVal psProperty As String _
1715 , Optional ByVal pvValue As Variant _
1716 ) As Boolean
1717 &apos;&apos;&apos; Set the new value of the named property
1718 &apos;&apos;&apos; Args:
1719 &apos;&apos;&apos; psProperty: the name of the property
1720 &apos;&apos;&apos; pvValue: the new value of the given property
1721 &apos;&apos;&apos; Returns:
1722 &apos;&apos;&apos; True if successful
1724 Dim bSet As Boolean &apos; Return value
1725 Dim vWhenFailure As Variant &apos; WhenAssertionFails allowed values
1726 Dim cstThisSub As String
1727 Const cstSubArgs = &quot;Value&quot;
1729 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
1730 bSet = False
1732 cstThisSub = &quot;SFUnitTests.UnitTest.set&quot; &amp; psProperty
1733 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
1735 bSet = True
1736 Select Case UCase(psProperty)
1737 Case UCase(&quot;LongMessage&quot;)
1738 If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;LongMessage&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
1739 _LongMessage = pvValue
1740 Case UCase(&quot;Verbose&quot;)
1741 If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Verbose&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
1742 _Verbose = pvValue
1743 Case UCase(&quot;WhenAssertionFails&quot;)
1744 If _ExecutionMode = SIMPLEMODE Then vWhenFailure = Array(0, 3) Else vWhenFailure = Array(0, 1, 2, 3)
1745 If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;WhenAssertionFails&quot;, ScriptForge.V_NUMERIC, vWhenFailure) Then GoTo Finally
1746 _WhenAssertionFails = pvValue
1747 Case Else
1748 bSet = False
1749 End Select
1751 Finally:
1752 _PropertySet = bSet
1753 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
1754 Exit Function
1755 Catch:
1756 GoTo Finally
1757 End Function &apos; SFUnitTests.SF_UnitTest._PropertySet
1759 REM -----------------------------------------------------------------------------
1760 Private Function _ReportMessage(ByVal psSysMessage As String _
1761 , Optional ByVal pvMessage As Variant _
1762 ) As Boolean
1763 &apos;&apos;&apos; Report in the console:
1764 &apos;&apos;&apos; - either the standard message
1765 &apos;&apos;&apos; - either the user message when not blank
1766 &apos;&apos;&apos; - or both
1767 &apos;&apos;&apos; Args:
1768 &apos;&apos;&apos; psSysMessage: the standard message as built by the calling routine
1769 &apos;&apos;&apos; psMessage: the message provided by the user script
1770 &apos;&apos;&apos; Returns:
1771 &apos;&apos;&apos; True when successful
1773 Dim bReport As Boolean &apos; Return value
1774 Dim sIndent As String &apos; Indentation spaces
1776 bReport = False
1777 On Local Error GoTo Catch
1778 If IsMissing(pvMessage) Or IsEmpty(pvMessage) Then pvMessage = &quot;&quot;
1780 Try:
1781 Select Case True
1782 Case Len(pvMessage) = 0
1783 Exception.DebugPrint(psSysMessage)
1784 Case _LongMessage
1785 Exception.DebugPrint(psSysMessage, pvMessage)
1786 Case Else
1787 Select Case _Status
1788 Case STATUSSTANDBY, STATUSSUITESTARTED : sIndent = &quot;&quot;
1789 Case STATUSSUITESTARTED : sIndent = Space(2)
1790 Case Else : sIndent = Space(4)
1791 End Select
1792 Exception.DebugPrint(sIndent &amp; pvMessage)
1793 End Select
1795 Finally:
1796 _ReportMessage = bReport
1797 Exit Function
1798 Catch:
1799 bReport = False
1800 GoTo Finally
1801 End Function &apos; SFUnitTests.SF_UnitTest._ReportMessage
1803 REM -----------------------------------------------------------------------------
1804 Private Function _Repr() As String
1805 &apos;&apos;&apos; Convert the UnitTest instance to a readable string, typically for debugging purposes (DebugPrint ...)
1806 &apos;&apos;&apos; Args:
1807 &apos;&apos;&apos; Return:
1808 &apos;&apos;&apos; &quot;[UnitTest]
1810 Const cstUnitTest = &quot;[UnitTest]&quot;
1811 Const cstMaxLength = 50 &apos; Maximum length for items
1813 _Repr = cstUnitTest
1815 End Function &apos; SFUnitTests.SF_UnitTest._Repr
1817 REM ============================================== END OF SFUNITTESTS.SF_UNITTEST
1818 </script:module>