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