+"""Copied from https://raw.githubusercontent.com/micropython/micropython-lib/cfa1b9cce0c93a3115bbff3886c9bbcddd9e8047/unittest/unittest.py """
+class SkipTest(Exception):
+ pass
+
+
+class AssertRaisesContext:
+
+ def __init__(self, exc):
+ self.expected = exc
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, tb):
+ if exc_type is None:
+ assert False, "%r not raised" % self.expected
+ if issubclass(exc_type, self.expected):
+ return True
+ return False
+
+
+class TestCase:
+
+ def fail(self, msg=''):
+ assert False, msg
+
+ def assertEqual(self, x, y, msg=''):
+ if not msg:
+ msg = "%r vs (expected) %r" % (x, y)
+ assert x == y, msg
+
+ def assertNotEqual(self, x, y, msg=''):
+ if not msg:
+ msg = "%r not expected to be equal %r" % (x, y)
+ assert x != y, msg
+
+ def assertAlmostEqual(self, x, y, places=None, msg='', delta=None):
+ if x == y:
+ return
+ if delta is not None and places is not None:
+ raise TypeError("specify delta or places not both")
+
+ if delta is not None:
+ if abs(x - y) <= delta:
+ return
+ if not msg:
+ msg = '%r != %r within %r delta' % (x, y, delta)
+ else:
+ if places is None:
+ places = 7
+ if round(abs(y-x), places) == 0:
+ return
+ if not msg:
+ msg = '%r != %r within %r places' % (x, y, places)
+
+ assert False, msg
+
+ def assertNotAlmostEqual(self, x, y, places=None, msg='', delta=None):
+ if delta is not None and places is not None:
+ raise TypeError("specify delta or places not both")
+
+ if delta is not None:
+ if not (x == y) and abs(x - y) > delta:
+ return
+ if not msg:
+ msg = '%r == %r within %r delta' % (x, y, delta)
+ else:
+ if places is None:
+ places = 7
+ if not (x == y) and round(abs(y-x), places) != 0:
+ return
+ if not msg:
+ msg = '%r == %r within %r places' % (x, y, places)
+
+ assert False, msg
+
+ def assertIs(self, x, y, msg=''):
+ if not msg:
+ msg = "%r is not %r" % (x, y)
+ assert x is y, msg
+
+ def assertIsNot(self, x, y, msg=''):
+ if not msg:
+ msg = "%r is %r" % (x, y)
+ assert x is not y, msg
+
+ def assertIsNone(self, x, msg=''):
+ if not msg:
+ msg = "%r is not None" % x
+ assert x is None, msg
+
+ def assertIsNotNone(self, x, msg=''):
+ if not msg:
+ msg = "%r is None" % x
+ assert x is not None, msg
+
+ def assertTrue(self, x, msg=''):
+ if not msg:
+ msg = "Expected %r to be True" % x
+ assert x, msg
+
+ def assertFalse(self, x, msg=''):
+ if not msg:
+ msg = "Expected %r to be False" % x
+ assert not x, msg
+
+ def assertIn(self, x, y, msg=''):
+ if not msg:
+ msg = "Expected %r to be in %r" % (x, y)
+ assert x in y, msg
+
+ def assertIsInstance(self, x, y, msg=''):
+ assert isinstance(x, y), msg
+
+ def assertRaises(self, exc, func=None, *args, **kwargs):
+ if func is None:
+ return AssertRaisesContext(exc)
+
+ try:
+ func(*args, **kwargs)
+ assert False, "%r not raised" % exc
+ except Exception as e:
+ if isinstance(e, exc):
+ return
+ raise
+
+
+
+def skip(msg):
+ def _decor(fun):
+ # We just replace original fun with _inner
+ def _inner(self):
+ raise SkipTest(msg)
+ return _inner
+ return _decor
+
+def skipIf(cond, msg):
+ if not cond:
+ return lambda x: x
+ return skip(msg)
+
+def skipUnless(cond, msg):
+ if cond:
+ return lambda x: x
+ return skip(msg)
+
+
+class TestSuite:
+ def __init__(self):
+ self.tests = []
+ def addTest(self, cls):
+ self.tests.append(cls)
+
+class TestRunner:
+ def run(self, suite):
+ res = TestResult()
+ for c in suite.tests:
+ run_class(c, res)
+
+ print("Ran %d tests\n" % res.testsRun)
+ if res.failuresNum > 0 or res.errorsNum > 0:
+ print("FAILED (failures=%d, errors=%d)" % (res.failuresNum, res.errorsNum))
+ else:
+ msg = "OK"
+ if res.skippedNum > 0:
+ msg += " (%d skipped)" % res.skippedNum
+ print(msg)
+
+ return res
+
+class TestResult:
+ def __init__(self):
+ self.errorsNum = 0
+ self.failuresNum = 0
+ self.skippedNum = 0
+ self.testsRun = 0
+
+ def wasSuccessful(self):
+ return self.errorsNum == 0 and self.failuresNum == 0
+
+# TODO: Uncompliant
+def run_class(c, test_result):
+ o = c()
+ set_up = getattr(o, "setUp", lambda: None)
+ tear_down = getattr(o, "tearDown", lambda: None)
+ for name in dir(o):
+ if name.startswith("test"):
+ print("%s (%s) ..." % (name, c.__qualname__), end="")
+ m = getattr(o, name)
+ set_up()
+ try:
+ test_result.testsRun += 1
+ m()
+ print(" ok")
+ except SkipTest as e:
+ print(" skipped:", e.args[0])
+ test_result.skippedNum += 1
+ except:
+ print(" FAIL")
+ test_result.failuresNum += 1
+ # Uncomment to investigate failure in detail
+ #raise
+ continue
+ finally:
+ tear_down()
+
+
+def main(module="__main__"):
+ def test_cases(m):
+ for tn in dir(m):
+ c = getattr(m, tn)
+ if isinstance(c, object) and isinstance(c, type) and issubclass(c, TestCase):
+ yield c
+
+ m = __import__(module, fromlist=['']) # changed to permit non-top-level testing modules
+ suite = TestSuite()
+ for c in test_cases(m):
+ suite.addTest(c)
+ runner = TestRunner()
+ result = runner.run(suite)
\ No newline at end of file