maxunit.bmx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. ' Copyright (c) 2006-2019 Bruce A Henderson
  2. '
  3. ' Permission is hereby granted, free of charge, to any person obtaining a copy
  4. ' of this software and associated documentation files (the "Software"), to deal
  5. ' in the Software without restriction, including without limitation the rights
  6. ' to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. ' copies of the Software, and to permit persons to whom the Software is
  8. ' furnished to do so, subject to the following conditions:
  9. '
  10. ' The above copyright notice and this permission notice shall be included in
  11. ' all copies or substantial portions of the Software.
  12. '
  13. ' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. ' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. ' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. ' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. ' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. ' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. ' THE SOFTWARE.
  20. '
  21. SuperStrict
  22. Rem
  23. bbdoc: MaxUnit - Unit Testing
  24. End Rem
  25. Module BRL.MaxUnit
  26. ModuleInfo "Version: 1.06"
  27. ModuleInfo "License: MIT"
  28. ModuleInfo "Author: Bruce A Henderson"
  29. ModuleInfo "Credit: Based loosely on the JUnit testing framework by Erich Gamma and Kent Beck. see junit.org"
  30. ModuleInfo "Copyright: (c) 2006-2019 Bruce A Henderson"
  31. ModuleInfo "History: 1.06"
  32. ModuleInfo "History: Added assertNull() and assertNotNull() pointer overloads."
  33. ModuleInfo "History: 1.05"
  34. ModuleInfo "History: Overloaded assertEquals() functions for NG."
  35. ModuleInfo "History: 1.04"
  36. ModuleInfo "History: Modified summary to count test runs, and tests."
  37. ModuleInfo "History: TTestSuite.run() now returns number of failures. (Muttley)"
  38. ModuleInfo "History: 1.03"
  39. ModuleInfo "History: Improved multiple test-types support."
  40. ModuleInfo "History: Changed tags to before/after and beforetype/aftertype"
  41. ModuleInfo "History: 1.02"
  42. ModuleInfo "History: Re-written to use reflection."
  43. ModuleInfo "History: 1.01"
  44. ModuleInfo "History: Added delta parameter for assertEqualsF and assertEqualsD"
  45. ModuleInfo "History: 1.00 Initial Release"
  46. Import BRL.LinkedList
  47. Import BRL.StandardIO
  48. Import BRL.System
  49. Import BRL.Reflection
  50. Rem
  51. bbdoc: A test defines a set of test methods to test.
  52. about: Extend TTest to define your own tests.
  53. <p>
  54. Tag a method with `{before}` and initiliaze any variables/data in that method
  55. </p>
  56. <p>
  57. Tag a method with `{after}` to release any permanent resources you allocated in the setup.
  58. </p>
  59. <p>
  60. For each test method you want to run, tag it with `{test}`
  61. </p>
  62. <p>
  63. Any methods not tagged are ignored by MaxUnit.
  64. </p>
  65. End Rem
  66. Type TTest Extends TAssert
  67. Field tests:TList = New TList
  68. Field failures:TList = New TList
  69. Field errors:TList = New TList
  70. Field currentTest:TTestFunction
  71. Field isFail:Int = False
  72. Field isError:Int = False
  73. 'Field column:Int = 0
  74. Field testCount:Int = 0
  75. Field startTime:Long = 0
  76. Field endTime:Long = 0
  77. Field _before:TMethod
  78. Field _after:TMethod
  79. Field _beforeType:TMethod
  80. Field _afterType:TMethod
  81. End Type
  82. Rem
  83. bbdoc: A test suite defines the fixture to run multiple tests.
  84. End Rem
  85. Type TTestSuite Extends TAssert
  86. Field tests:TList = New TList
  87. Field failures:TList = New TList
  88. Field errors:TList = New TList
  89. Field currentTest:TTestFunction
  90. Field isFail:Int = False
  91. Field isError:Int = False
  92. Field column:Int = 0
  93. Field testCount:Int = 0
  94. Field startTime:Long = 0
  95. Method _addTest(instance:Object)
  96. tests.addLast(instance)
  97. End Method
  98. Method _add:TTestFunction(instance:Object, f:TMethod )
  99. Local t:TTestFunction = New TTestFunction
  100. t.name = TTypeId.ForObject(instance).Name() + "." + f.Name()
  101. t.instance = instance
  102. t.test = f
  103. TTest(instance).tests.addLast(t)
  104. Return t
  105. End Method
  106. Rem
  107. bbdoc: Runs the suite of tests.
  108. End Rem
  109. Method run:Int()
  110. startTime = MilliSecs()
  111. _addTests()
  112. _PrintLine("")
  113. _Print("[0] ")
  114. Local subTestCount:Int = 0
  115. For Local testType:TTest = EachIn tests
  116. testType.startTime = MilliSecs()
  117. Local size:Int = testType.tests.count()
  118. Local count:Int = 0, doBefore:Int, doAfter:Int
  119. For Local t:TTestFunction = EachIn testType.tests
  120. If Not count Then
  121. doBefore = True
  122. End If
  123. If count = size - 1 Then
  124. doAfter = True
  125. End If
  126. subTestCount:+ 1
  127. performTest(t, doBefore, doAfter)
  128. Next
  129. testType.endTime = MilliSecs()
  130. Next
  131. Local endTime:Long = MilliSecs()
  132. _PrintLine("")
  133. Local f:Int = failures.count()
  134. Local e:Int = errors.count()
  135. If f > 0 Or e > 0 Then
  136. _PrintLine("")
  137. If f > 0 Then
  138. _Print("There ")
  139. If f <> 1 Then
  140. _Print("were " + f + " failures")
  141. Else
  142. _Print("was 1 failure")
  143. End If
  144. _PrintLine(":")
  145. Local c:Int = 1
  146. For Local t:TTestFunction = EachIn failures
  147. _PrintLine( c + ") " + t.name)
  148. _PrintLine(" " + t.reason)
  149. _PrintLine("")
  150. c:+ 1
  151. Next
  152. End If
  153. If e > 0 Then
  154. ' add a spacer
  155. If f > 0 Then
  156. _PrintLine("")
  157. _PrintLine("")
  158. End If
  159. _Print("There ")
  160. If e <> 1 Then
  161. _Print("were " + e + " errors")
  162. Else
  163. _Print("was 1 error")
  164. End If
  165. _PrintLine(":")
  166. Local c:Int = 1
  167. For Local t:TTestFunction = EachIn errors
  168. _PrintLine( c + ") " + t.name)
  169. _PrintLine(" " + t.reason)
  170. _PrintLine("")
  171. c:+ 1
  172. Next
  173. End If
  174. _PrintLine("")
  175. _PrintLine("FAILURES!!!")
  176. _PrintLine("Test Runs: " + tests.count() + ", Tests: " + subTestCount + ..
  177. ", Failures: " + f + ", Errors: " + e )
  178. Else
  179. _Print("OK (" + subTestCount + " test")
  180. If tests.count() <> 1 Then
  181. _Print("s")
  182. End If
  183. _PrintLine(")")
  184. End If
  185. _PrintLine("Time: " + ((endTime - startTime)/1000) + "." + (((endTime - startTime) Mod 1000)))
  186. Return f
  187. End Method
  188. Method performTest(t:TTestFunction, First:Int = False, last:Int = False)
  189. isFail = False
  190. isError = False
  191. ' This is the current test
  192. currentTest = t
  193. If First Then
  194. Try
  195. ' run any user-specific pre-test setup
  196. If TTest(t.instance)._beforeType Then
  197. TTest(t.instance)._beforeType.Invoke(t.instance, Null)
  198. End If
  199. Catch ex:Object
  200. isError = True
  201. t.reason = "Exception in beforeType() - " + ex.toString()
  202. End Try
  203. End If
  204. Try
  205. ' run any user-specific setup
  206. If TTest(t.instance)._before Then
  207. TTest(t.instance)._before.Invoke(t.instance, Null)
  208. End If
  209. Catch ex:Object
  210. isError = True
  211. t.reason = "Exception in before() - " + ex.toString()
  212. End Try
  213. ' +++++++++++++++++++++++++++
  214. If Not isError Then
  215. Try
  216. ' run the test function
  217. t.test.Invoke(t.instance, Null)
  218. Catch ex:AssertionFailedException
  219. isFail = True
  220. t.reason = ex.toString()
  221. Catch ex:Object
  222. isError = True
  223. t.reason = "Exception - " + ex.toString()
  224. End Try
  225. End If
  226. ' +++++++++++++++++++++++++++
  227. Try
  228. ' run any user-specific teardown
  229. If TTest(t.instance)._after Then
  230. TTest(t.instance)._after.Invoke(t.instance, Null)
  231. End If
  232. Catch ex:Object
  233. isError = True
  234. t.reason = "Exception in after() - " + ex.toString()
  235. End Try
  236. If last Then
  237. Try
  238. ' run any user-specific post-test setup
  239. If TTest(t.instance)._afterType Then
  240. TTest(t.instance)._afterType.Invoke(t.instance, Null)
  241. End If
  242. Catch ex:Object
  243. isError = True
  244. t.reason = "Exception in afterType() - " + ex.toString()
  245. End Try
  246. End If
  247. If Not isFail Then
  248. If Not isError Then
  249. _Print(".")
  250. Else
  251. errors.addLast(currentTest)
  252. _Print("E")
  253. End If
  254. Else
  255. failures.addLast(currentTest)
  256. _Print("F")
  257. End If
  258. column:+ 1
  259. If column > 40 Then
  260. _PrintLine("")
  261. _Print("[" + testCount + "] ")
  262. column = 0
  263. End If
  264. testCount:+1
  265. End Method
  266. Function _Print( str:String="" )
  267. StandardIOStream.WriteString str
  268. StandardIOStream.Flush
  269. End Function
  270. Function _PrintLine( str:String="" )
  271. StandardIOStream.WriteLine str
  272. StandardIOStream.Flush
  273. End Function
  274. Method _addTests()
  275. ' This is the base type, TTest. We'll run tests on all Types that extend it.
  276. Local idTest:TTypeId = TTypeId.ForName("TTest")
  277. _addTests(idTest)
  278. End Method
  279. Method _addTests(baseIdType:TTypeId)
  280. ' process each derived type...
  281. For Local id:TTypeId = EachIn baseIdType.DerivedTypes()
  282. Local obj:Object = Null
  283. For Local meth:TMethod = EachIn id.EnumMethods()
  284. If Not obj Then
  285. obj = id.NewObject()
  286. _addTest(obj)
  287. End If
  288. If meth.MetaData("test") Then ' a test method
  289. _add(obj, meth)
  290. End If
  291. If meth.MetaData("before") Then ' a setup method
  292. Local f:TField = id.FindField("_before")
  293. f.Set(obj, meth)
  294. End If
  295. If meth.MetaData("after") Then ' a teardown method
  296. Local f:TField = id.FindField("_after")
  297. f.Set(obj, meth)
  298. End If
  299. If meth.MetaData("beforetype") Then ' a setup method
  300. Local f:TField = id.FindField("_beforetype")
  301. f.Set(obj, meth)
  302. End If
  303. If meth.MetaData("aftertype") Then ' a teardown method
  304. Local f:TField = id.FindField("_aftertype")
  305. f.Set(obj, meth)
  306. End If
  307. Next
  308. _addTests(id)
  309. Next
  310. End Method
  311. End Type
  312. Type TTestFunction
  313. Field name:String
  314. Field test:TMethod
  315. Field reason:String
  316. Field instance:Object
  317. End Type
  318. Rem
  319. bbdoc: Failed assertion.
  320. End Rem
  321. Type AssertionFailedException
  322. Field message:String
  323. Function Create:AssertionFailedException(message:String)
  324. Local this:AssertionFailedException = New AssertionFailedException
  325. this.message = message
  326. Return this
  327. End Function
  328. Method toString:String() Override
  329. Return message
  330. End Method
  331. End Type
  332. Rem
  333. bbdoc: A set of assert methods.
  334. about: Messages are only displayed when an assert fails.
  335. End Rem
  336. Type TAssert
  337. Rem
  338. bbdoc: Asserts that a condition is #True.
  339. about: If it isn't #True, it throws an #AssertionFailedException with the given message.
  340. End Rem
  341. Function assertTrue(bool:Int, message:String = Null)
  342. If Not bool Then
  343. fail("assertTrue() : " + message)
  344. End If
  345. End Function
  346. Rem
  347. bbdoc: Asserts that a condition is #False.
  348. about: If it isn't #False, it throws an #AssertionFailedException with the given message.
  349. End Rem
  350. Function assertFalse(bool:Int, message:String = Null)
  351. If bool Then
  352. fail("assertFalse() : " + message)
  353. End If
  354. End Function
  355. Rem
  356. bbdoc: Fails a test with the given message.
  357. End Rem
  358. Function fail(message:String)
  359. Throw AssertionFailedException.Create(message)
  360. End Function
  361. Rem
  362. bbdoc: Asserts that two objects are equal.
  363. about: If they are not equal, an #AssertionFailedException is thrown with the given message.
  364. End Rem
  365. Function assertEquals(expected:Object, actual:Object, message:String = Null)
  366. If expected = Null And actual = Null Then
  367. Return
  368. End If
  369. If expected <> Null And expected.compare(actual) = 0 Then
  370. Return
  371. End If
  372. failNotEquals(expected, actual, "assertEquals() : " + message)
  373. End Function
  374. Rem
  375. bbdoc: Asserts that two ints are equal.
  376. about: If they are not equal, an #AssertionFailedException is thrown with the given message.
  377. End Rem
  378. Function assertEqualsI(expected:Int, actual:Int, message:String = Null)
  379. If expected = Null And actual = Null Then
  380. Return
  381. End If
  382. If expected <> Null And actual <> Null Then
  383. If expected = actual Then
  384. Return
  385. End If
  386. End If
  387. failNotEquals(String.fromInt(expected), String.fromInt(actual), "assertEqualsI() : " +message)
  388. End Function
  389. Rem
  390. bbdoc: Asserts that two longs are equal.
  391. about: If they are not equal an #AssertionFailedException is thrown with the given message.
  392. End Rem
  393. Function assertEqualsL(expected:Long, actual:Long, message:String = Null)
  394. If expected = Null And actual = Null Then
  395. Return
  396. End If
  397. If expected <> Null And actual <> Null Then
  398. If expected = actual Then
  399. Return
  400. End If
  401. End If
  402. failNotEquals(String.fromLong(expected), String.fromLong(actual), "assertEqualsL() : " +message)
  403. End Function
  404. Rem
  405. bbdoc: Asserts that two floats are equal.
  406. about: If they are not equal, an #AssertionFailedException is thrown with the given message.
  407. End Rem
  408. Function assertEqualsF(expected:Float, actual:Float, delta:Float = 0, message:String = Null)
  409. If expected = Null And actual = Null Then
  410. Return
  411. End If
  412. If expected <> Null And actual <> Null Then
  413. If expected = actual Then
  414. Return
  415. End If
  416. End If
  417. If Not(Abs(expected - actual) <= delta) Then
  418. failNotEquals(String.fromFloat(expected), String.fromFloat(actual), "assertEqualsF() : " +message)
  419. End If
  420. End Function
  421. Rem
  422. bbdoc: Asserts that two doubles are equal.
  423. about: If they are not equal, an #AssertionFailedException is thrown with the given message.
  424. End Rem
  425. Function assertEqualsD(expected:Double, actual:Double, delta:Double = 0, message:String = Null)
  426. If expected = Null And actual = Null Then
  427. Return
  428. End If
  429. If expected <> Null And actual <> Null Then
  430. If expected = actual Then
  431. Return
  432. End If
  433. End If
  434. If Not(Abs(expected - actual) <= delta) Then
  435. failNotEquals(String.fromDouble(expected), String.fromDouble(actual), "assertEqualsD() : " +message)
  436. End If
  437. End Function
  438. Rem
  439. bbdoc: Asserts that two shorts are equal.
  440. about: If they are not equal, an #AssertionFailedException is thrown with the given message.
  441. End Rem
  442. Function assertEqualsS(expected:Short, actual:Short, message:String = Null)
  443. If expected = Null And actual = Null Then
  444. Return
  445. End If
  446. If expected <> Null And actual <> Null Then
  447. If expected = actual Then
  448. Return
  449. End If
  450. End If
  451. failNotEquals(String.fromInt(expected), String.fromInt(actual), "assertEqualsS() : " +message)
  452. End Function
  453. Rem
  454. bbdoc: Asserts that two bytes are equal.
  455. about: If they are not equal, an #AssertionFailedException is thrown with the given message.
  456. End Rem
  457. Function assertEqualsB(expected:Byte, actual:Byte, message:String = Null)
  458. If expected = Null And actual = Null Then
  459. Return
  460. End If
  461. If expected <> Null And actual <> Null Then
  462. If expected = actual Then
  463. Return
  464. End If
  465. End If
  466. failNotEquals(String.fromInt(expected), String.fromInt(actual), "assertEqualsB() : " + message)
  467. End Function
  468. Rem
  469. bbdoc: Asserts that an object isn't #Null.
  470. about: If it is #Null, an #AssertionFailedException is thrown with the given message.
  471. End Rem
  472. Function assertNotNull(obj:Object, message:String = Null)
  473. If obj = Null Or IsEmptyArray(obj) Or IsEmptyString(obj) Then
  474. fail("assertNotNull() : " + message)
  475. End If
  476. End Function
  477. Rem
  478. bbdoc: Asserts that a pointer isn't #Null.
  479. about: If it is #Null, an #AssertionFailedException is thrown with the given message.
  480. End Rem
  481. Function assertNotNull(value:Byte Ptr, message:String = Null)
  482. If value = Null Then
  483. fail("assertNotNull() : " + message)
  484. End If
  485. End Function
  486. Rem
  487. bbdoc: Asserts that an #Object is #Null.
  488. about:
  489. If it is not #Null, an #AssertionFailedException is thrown with the given message.
  490. End Rem
  491. Function assertNull(obj:Object, message:String = Null)
  492. If obj <> Null And Not IsEmptyArray(obj) And Not IsEmptyString(obj) Then
  493. fail("assertNull() : " + message)
  494. End If
  495. End Function
  496. Rem
  497. bbdoc: Asserts that two objects refer to the same #Object.
  498. about: If they are not the same, an #AssertionFailedException is thrown with the given message.
  499. End Rem
  500. Function assertSame(expected:Object, actual:Object, message:String = Null)
  501. If expected = actual Then
  502. Return
  503. End If
  504. failNotSame(expected, actual, "assertSame() : " + message)
  505. End Function
  506. Rem
  507. bbdoc: Asserts that an pointer is #Null.
  508. about:
  509. If it is not #Null, an #AssertionFailedException is thrown with the given message.
  510. End Rem
  511. Function assertNull(value:Byte Ptr, message:String = Null)
  512. If value <> Null Then
  513. fail("assertNull() : " + message)
  514. End If
  515. End Function
  516. Rem
  517. bbdoc: Asserts that two objects refer to different objects.
  518. about: If they are the same, an #AssertionFailedException is thrown with the given message.
  519. End Rem
  520. Function assertNotSame(expected:Object, actual:Object, message:String = Null)
  521. If expected = actual Then
  522. failSame("assertNotSame() : " + message)
  523. End If
  524. End Function
  525. Function failSame(message:String)
  526. Local formatted:String = ""
  527. If message <> Null Then
  528. formatted = message + " "
  529. End If
  530. fail(formatted + "expected not same")
  531. End Function
  532. Function failNotSame(expected:Object, actual:Object, message:String = Null)
  533. Local formatted:String = ""
  534. If message <> Null Then
  535. formatted= message + " "
  536. End If
  537. fail(formatted + "expected same:<" + expected.toString() + "> was not:<" + actual.toString() + ">")
  538. End Function
  539. Function failNotEquals(expected:Object, actual:Object, message:String = Null)
  540. fail(format(expected, actual, message))
  541. End Function
  542. Function format:String(expected:Object, actual:Object, message:String = Null)
  543. Local formatted:String = ""
  544. If message <> Null Then
  545. formatted = message + " "
  546. End If
  547. Return formatted + "expected:<" + expected.toString() + "> but was:<" + actual.toString() + ">"
  548. End Function
  549. Function assertEquals(expected:Int, actual:Int, message:String = Null)
  550. assertEqualsI(expected, actual, message)
  551. End Function
  552. Function assertEquals(expected:Long, actual:Long, message:String = Null)
  553. assertEqualsL(expected, actual, message)
  554. End Function
  555. Function assertEquals(expected:Float, actual:Float, delta:Float = 0, message:String = Null)
  556. assertEqualsF(expected, actual, delta, message)
  557. End Function
  558. Function assertEquals(expected:Double, actual:Double, delta:Double = 0, message:String = Null)
  559. assertEqualsD(expected, actual, delta, message)
  560. End Function
  561. Function assertEquals(expected:Short, actual:Short, message:String = Null)
  562. assertEqualsS(expected, actual, message)
  563. End Function
  564. Function assertEquals(expected:Byte, actual:Byte, message:String = Null)
  565. assertEqualsB(expected, actual, message)
  566. End Function
  567. Rem
  568. bbdoc: Asserts that two UInts are equal.
  569. about: If they are not equal, an #AssertionFailedException is thrown with the given message.
  570. End Rem
  571. Function assertEquals(expected:UInt, actual:UInt, message:String = Null)
  572. If expected = Null And actual = Null Then
  573. Return
  574. End If
  575. If expected <> Null And actual <> Null Then
  576. If expected = actual Then
  577. Return
  578. End If
  579. End If
  580. failNotEquals(String.fromUInt(expected), String.fromUInt(actual), "assertEquals() : " +message)
  581. End Function
  582. Rem
  583. bbdoc: Asserts that two ULongs are equal.
  584. about: If they are not equal, an #AssertionFailedException is thrown with the given message.
  585. End Rem
  586. Function assertEquals(expected:ULong, actual:ULong, message:String = Null)
  587. If expected = Null And actual = Null Then
  588. Return
  589. End If
  590. If expected <> Null And actual <> Null Then
  591. If expected = actual Then
  592. Return
  593. End If
  594. End If
  595. failNotEquals(String.fromULong(expected), String.fromULong(actual), "assertEquals() : " +message)
  596. End Function
  597. Rem
  598. bbdoc: Asserts that two Size_Ts are equal.
  599. about: If they are not equal, an #AssertionFailedException is thrown with the given message.
  600. End Rem
  601. Function assertEquals(expected:Size_T, actual:Size_T, message:String = Null)
  602. If expected = Null And actual = Null Then
  603. Return
  604. End If
  605. If expected <> Null And actual <> Null Then
  606. If expected = actual Then
  607. Return
  608. End If
  609. End If
  610. failNotEquals(String.fromSizeT(expected), String.fromSizeT(actual), "assertEquals() : " +message)
  611. End Function
  612. End Type