You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
6.3 KiB

  1. """Based on https://raw.githubusercontent.com/micropython/micropython-lib/cfa1b9cce0c93a3115bbff3886c9bbcddd9e8047/unittest/unittest.py """
  2. import sys
  3. class SkipTest(Exception):
  4. pass
  5. raiseException = False
  6. raiseBaseException = True
  7. class AssertRaisesContext:
  8. def __init__(self, exc):
  9. self.expected = exc
  10. def __enter__(self):
  11. return self
  12. def __exit__(self, exc_type, exc_value, tb):
  13. if exc_type is None:
  14. assert False, "%r not raised" % self.expected
  15. if issubclass(exc_type, self.expected):
  16. return True
  17. return False
  18. class TestCase:
  19. def fail(self, msg=''):
  20. assert False, msg
  21. def assertEqual(self, x, y, msg=''):
  22. if not msg:
  23. msg = "%r vs (expected) %r" % (x, y)
  24. assert x == y, msg
  25. def assertNotEqual(self, x, y, msg=''):
  26. if not msg:
  27. msg = "%r not expected to be equal %r" % (x, y)
  28. assert x != y, msg
  29. def assertAlmostEqual(self, x, y, places=None, msg='', delta=None):
  30. if x == y:
  31. return
  32. if delta is not None and places is not None:
  33. raise TypeError("specify delta or places not both")
  34. if delta is not None:
  35. if abs(x - y) <= delta:
  36. return
  37. if not msg:
  38. msg = '%r != %r within %r delta' % (x, y, delta)
  39. else:
  40. if places is None:
  41. places = 7
  42. if round(abs(y-x), places) == 0:
  43. return
  44. if not msg:
  45. msg = '%r != %r within %r places' % (x, y, places)
  46. assert False, msg
  47. def assertNotAlmostEqual(self, x, y, places=None, msg='', delta=None):
  48. if delta is not None and places is not None:
  49. raise TypeError("specify delta or places not both")
  50. if delta is not None:
  51. if not (x == y) and abs(x - y) > delta:
  52. return
  53. if not msg:
  54. msg = '%r == %r within %r delta' % (x, y, delta)
  55. else:
  56. if places is None:
  57. places = 7
  58. if not (x == y) and round(abs(y-x), places) != 0:
  59. return
  60. if not msg:
  61. msg = '%r == %r within %r places' % (x, y, places)
  62. assert False, msg
  63. def assertIs(self, x, y, msg=''):
  64. if not msg:
  65. msg = "%r is not %r" % (x, y)
  66. assert x is y, msg
  67. def assertIsNot(self, x, y, msg=''):
  68. if not msg:
  69. msg = "%r is %r" % (x, y)
  70. assert x is not y, msg
  71. def assertIsNone(self, x, msg=''):
  72. if not msg:
  73. msg = "%r is not None" % x
  74. assert x is None, msg
  75. def assertIsNotNone(self, x, msg=''):
  76. if not msg:
  77. msg = "%r is None" % x
  78. assert x is not None, msg
  79. def assertTrue(self, x, msg=''):
  80. if not msg:
  81. msg = "Expected %r to be True" % x
  82. assert x, msg
  83. def assertFalse(self, x, msg=''):
  84. if not msg:
  85. msg = "Expected %r to be False" % x
  86. assert not x, msg
  87. def assertIn(self, x, y, msg=''):
  88. if not msg:
  89. msg = "Expected %r to be in %r" % (x, y)
  90. assert x in y, msg
  91. def assertIsInstance(self, x, y, msg=''):
  92. assert isinstance(x, y), msg
  93. def assertRaises(self, exc, func=None, *args, **kwargs):
  94. if func is None:
  95. return AssertRaisesContext(exc)
  96. try:
  97. func(*args, **kwargs)
  98. assert False, "%r not raised" % exc
  99. except Exception as e:
  100. if isinstance(e, exc):
  101. return
  102. raise
  103. def skip(msg):
  104. def _decor(fun):
  105. # We just replace original fun with _inner
  106. def _inner(self):
  107. raise SkipTest(msg)
  108. return _inner
  109. return _decor
  110. def skipIf(cond, msg):
  111. if not cond:
  112. return lambda x: x
  113. return skip(msg)
  114. def skipUnless(cond, msg):
  115. if cond:
  116. return lambda x: x
  117. return skip(msg)
  118. class TestSuite:
  119. def __init__(self):
  120. self.tests = []
  121. def addTest(self, cls):
  122. self.tests.append(cls)
  123. class TestRunner:
  124. def run(self, suite):
  125. res = TestResult()
  126. for c in suite.tests:
  127. run_class(c, res)
  128. print("Ran %d tests\n" % res.testsRun)
  129. if res.failuresNum > 0 or res.errorsNum > 0:
  130. print("FAILED (failures=%d, errors=%d)" % (res.failuresNum, res.errorsNum))
  131. else:
  132. msg = "OK"
  133. if res.skippedNum > 0:
  134. msg += " (%d skipped)" % res.skippedNum
  135. print(msg)
  136. return res
  137. class TestResult:
  138. def __init__(self):
  139. self.errorsNum = 0
  140. self.failuresNum = 0
  141. self.skippedNum = 0
  142. self.testsRun = 0
  143. def wasSuccessful(self):
  144. return self.errorsNum == 0 and self.failuresNum == 0
  145. # TODO: Uncompliant
  146. def run_class(c, test_result):
  147. o = c()
  148. set_up = getattr(o, "setUp", lambda: None)
  149. tear_down = getattr(o, "tearDown", lambda: None)
  150. for name in dir(o):
  151. if name.startswith("test"):
  152. print("%s (%s) ..." % (name, c.__qualname__), end="")
  153. m = getattr(o, name)
  154. set_up()
  155. try:
  156. test_result.testsRun += 1
  157. m()
  158. print(" ok")
  159. except SkipTest as e:
  160. print(" skipped:", e.args[0])
  161. test_result.skippedNum += 1
  162. except Exception as e: # user exception
  163. print(" FAIL")
  164. if raiseException:
  165. raise
  166. else:
  167. print(e)
  168. test_result.failuresNum += 1
  169. continue
  170. except BaseException as e: # system exception
  171. print(" FAIL")
  172. if raiseBaseException:
  173. raise
  174. else:
  175. print(e)
  176. test_result.failuresNum += 1
  177. continue
  178. finally:
  179. tear_down()
  180. def main(module="__main__"):
  181. def test_cases(m):
  182. for tn in dir(m):
  183. c = getattr(m, tn)
  184. if isinstance(c, object) and isinstance(c, type) and issubclass(c, TestCase):
  185. yield c
  186. m = __import__(module) # changed to permit non-top-level testing modules
  187. suite = TestSuite()
  188. for c in test_cases(m):
  189. suite.addTest(c)
  190. runner = TestRunner()
  191. result = runner.run(suite)