SF_UnitTest.xba 78 KB

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