1import datetime
2import warnings
3import weakref
4import unittest
5from itertools import product
6
7
8class Test_Assertions(unittest.TestCase):
9    def test_AlmostEqual(self):
10        self.assertAlmostEqual(1.00000001, 1.0)
11        self.assertNotAlmostEqual(1.0000001, 1.0)
12        self.assertRaises(self.failureException,
13                          self.assertAlmostEqual, 1.0000001, 1.0)
14        self.assertRaises(self.failureException,
15                          self.assertNotAlmostEqual, 1.00000001, 1.0)
16
17        self.assertAlmostEqual(1.1, 1.0, places=0)
18        self.assertRaises(self.failureException,
19                          self.assertAlmostEqual, 1.1, 1.0, places=1)
20
21        self.assertAlmostEqual(0, .1+.1j, places=0)
22        self.assertNotAlmostEqual(0, .1+.1j, places=1)
23        self.assertRaises(self.failureException,
24                          self.assertAlmostEqual, 0, .1+.1j, places=1)
25        self.assertRaises(self.failureException,
26                          self.assertNotAlmostEqual, 0, .1+.1j, places=0)
27
28        self.assertAlmostEqual(float('inf'), float('inf'))
29        self.assertRaises(self.failureException, self.assertNotAlmostEqual,
30                          float('inf'), float('inf'))
31
32    def test_AmostEqualWithDelta(self):
33        self.assertAlmostEqual(1.1, 1.0, delta=0.5)
34        self.assertAlmostEqual(1.0, 1.1, delta=0.5)
35        self.assertNotAlmostEqual(1.1, 1.0, delta=0.05)
36        self.assertNotAlmostEqual(1.0, 1.1, delta=0.05)
37
38        self.assertAlmostEqual(1.0, 1.0, delta=0.5)
39        self.assertRaises(self.failureException, self.assertNotAlmostEqual,
40                          1.0, 1.0, delta=0.5)
41
42        self.assertRaises(self.failureException, self.assertAlmostEqual,
43                          1.1, 1.0, delta=0.05)
44        self.assertRaises(self.failureException, self.assertNotAlmostEqual,
45                          1.1, 1.0, delta=0.5)
46
47        self.assertRaises(TypeError, self.assertAlmostEqual,
48                          1.1, 1.0, places=2, delta=2)
49        self.assertRaises(TypeError, self.assertNotAlmostEqual,
50                          1.1, 1.0, places=2, delta=2)
51
52        first = datetime.datetime.now()
53        second = first + datetime.timedelta(seconds=10)
54        self.assertAlmostEqual(first, second,
55                               delta=datetime.timedelta(seconds=20))
56        self.assertNotAlmostEqual(first, second,
57                                  delta=datetime.timedelta(seconds=5))
58
59    def test_assertRaises(self):
60        def _raise(e):
61            raise e
62        self.assertRaises(KeyError, _raise, KeyError)
63        self.assertRaises(KeyError, _raise, KeyError("key"))
64        try:
65            self.assertRaises(KeyError, lambda: None)
66        except self.failureException as e:
67            self.assertIn("KeyError not raised", str(e))
68        else:
69            self.fail("assertRaises() didn't fail")
70        try:
71            self.assertRaises(KeyError, _raise, ValueError)
72        except ValueError:
73            pass
74        else:
75            self.fail("assertRaises() didn't let exception pass through")
76        with self.assertRaises(KeyError) as cm:
77            try:
78                raise KeyError
79            except Exception as e:
80                exc = e
81                raise
82        self.assertIs(cm.exception, exc)
83
84        with self.assertRaises(KeyError):
85            raise KeyError("key")
86        try:
87            with self.assertRaises(KeyError):
88                pass
89        except self.failureException as e:
90            self.assertIn("KeyError not raised", str(e))
91        else:
92            self.fail("assertRaises() didn't fail")
93        try:
94            with self.assertRaises(KeyError):
95                raise ValueError
96        except ValueError:
97            pass
98        else:
99            self.fail("assertRaises() didn't let exception pass through")
100
101    def test_assertRaises_frames_survival(self):
102        # Issue #9815: assertRaises should avoid keeping local variables
103        # in a traceback alive.
104        class A:
105            pass
106        wr = None
107
108        class Foo(unittest.TestCase):
109
110            def foo(self):
111                nonlocal wr
112                a = A()
113                wr = weakref.ref(a)
114                try:
115                    raise OSError
116                except OSError:
117                    raise ValueError
118
119            def test_functional(self):
120                self.assertRaises(ValueError, self.foo)
121
122            def test_with(self):
123                with self.assertRaises(ValueError):
124                    self.foo()
125
126        Foo("test_functional").run()
127        self.assertIsNone(wr())
128        Foo("test_with").run()
129        self.assertIsNone(wr())
130
131    def testAssertNotRegex(self):
132        self.assertNotRegex('Ala ma kota', r'r+')
133        try:
134            self.assertNotRegex('Ala ma kota', r'k.t', 'Message')
135        except self.failureException as e:
136            self.assertIn('Message', e.args[0])
137        else:
138            self.fail('assertNotRegex should have failed.')
139
140
141class TestLongMessage(unittest.TestCase):
142    """Test that the individual asserts honour longMessage.
143    This actually tests all the message behaviour for
144    asserts that use longMessage."""
145
146    def setUp(self):
147        class TestableTestFalse(unittest.TestCase):
148            longMessage = False
149            failureException = self.failureException
150
151            def testTest(self):
152                pass
153
154        class TestableTestTrue(unittest.TestCase):
155            longMessage = True
156            failureException = self.failureException
157
158            def testTest(self):
159                pass
160
161        self.testableTrue = TestableTestTrue('testTest')
162        self.testableFalse = TestableTestFalse('testTest')
163
164    def testDefault(self):
165        self.assertTrue(unittest.TestCase.longMessage)
166
167    def test_formatMsg(self):
168        self.assertEqual(self.testableFalse._formatMessage(None, "foo"), "foo")
169        self.assertEqual(self.testableFalse._formatMessage("foo", "bar"), "foo")
170
171        self.assertEqual(self.testableTrue._formatMessage(None, "foo"), "foo")
172        self.assertEqual(self.testableTrue._formatMessage("foo", "bar"), "bar : foo")
173
174        # This blows up if _formatMessage uses string concatenation
175        self.testableTrue._formatMessage(object(), 'foo')
176
177    def test_formatMessage_unicode_error(self):
178        one = ''.join(chr(i) for i in range(255))
179        # this used to cause a UnicodeDecodeError constructing msg
180        self.testableTrue._formatMessage(one, '\uFFFD')
181
182    def assertMessages(self, methodName, args, errors):
183        """
184        Check that methodName(*args) raises the correct error messages.
185        errors should be a list of 4 regex that match the error when:
186          1) longMessage = False and no msg passed;
187          2) longMessage = False and msg passed;
188          3) longMessage = True and no msg passed;
189          4) longMessage = True and msg passed;
190        """
191        def getMethod(i):
192            useTestableFalse  = i < 2
193            if useTestableFalse:
194                test = self.testableFalse
195            else:
196                test = self.testableTrue
197            return getattr(test, methodName)
198
199        for i, expected_regex in enumerate(errors):
200            testMethod = getMethod(i)
201            kwargs = {}
202            withMsg = i % 2
203            if withMsg:
204                kwargs = {"msg": "oops"}
205
206            with self.assertRaisesRegex(self.failureException,
207                                        expected_regex=expected_regex):
208                testMethod(*args, **kwargs)
209
210    def testAssertTrue(self):
211        self.assertMessages('assertTrue', (False,),
212                            ["^False is not true$", "^oops$", "^False is not true$",
213                             "^False is not true : oops$"])
214
215    def testAssertFalse(self):
216        self.assertMessages('assertFalse', (True,),
217                            ["^True is not false$", "^oops$", "^True is not false$",
218                             "^True is not false : oops$"])
219
220    def testNotEqual(self):
221        self.assertMessages('assertNotEqual', (1, 1),
222                            ["^1 == 1$", "^oops$", "^1 == 1$",
223                             "^1 == 1 : oops$"])
224
225    def testAlmostEqual(self):
226        self.assertMessages(
227            'assertAlmostEqual', (1, 2),
228            [r"^1 != 2 within 7 places \(1 difference\)$", "^oops$",
229             r"^1 != 2 within 7 places \(1 difference\)$",
230             r"^1 != 2 within 7 places \(1 difference\) : oops$"])
231
232    def testNotAlmostEqual(self):
233        self.assertMessages('assertNotAlmostEqual', (1, 1),
234                            ["^1 == 1 within 7 places$", "^oops$",
235                             "^1 == 1 within 7 places$", "^1 == 1 within 7 places : oops$"])
236
237    def test_baseAssertEqual(self):
238        self.assertMessages('_baseAssertEqual', (1, 2),
239                            ["^1 != 2$", "^oops$", "^1 != 2$", "^1 != 2 : oops$"])
240
241    def testAssertSequenceEqual(self):
242        # Error messages are multiline so not testing on full message
243        # assertTupleEqual and assertListEqual delegate to this method
244        self.assertMessages('assertSequenceEqual', ([], [None]),
245                            [r"\+ \[None\]$", "^oops$", r"\+ \[None\]$",
246                             r"\+ \[None\] : oops$"])
247
248    def testAssertSetEqual(self):
249        self.assertMessages('assertSetEqual', (set(), set([None])),
250                            ["None$", "^oops$", "None$",
251                             "None : oops$"])
252
253    def testAssertIn(self):
254        self.assertMessages('assertIn', (None, []),
255                            [r'^None not found in \[\]$', "^oops$",
256                             r'^None not found in \[\]$',
257                             r'^None not found in \[\] : oops$'])
258
259    def testAssertNotIn(self):
260        self.assertMessages('assertNotIn', (None, [None]),
261                            [r'^None unexpectedly found in \[None\]$', "^oops$",
262                             r'^None unexpectedly found in \[None\]$',
263                             r'^None unexpectedly found in \[None\] : oops$'])
264
265    def testAssertDictEqual(self):
266        self.assertMessages('assertDictEqual', ({}, {'key': 'value'}),
267                            [r"\+ \{'key': 'value'\}$", "^oops$",
268                             r"\+ \{'key': 'value'\}$",
269                             r"\+ \{'key': 'value'\} : oops$"])
270
271    def testAssertDictContainsSubset(self):
272        with warnings.catch_warnings():
273            warnings.simplefilter("ignore", DeprecationWarning)
274
275            self.assertMessages('assertDictContainsSubset', ({'key': 'value'}, {}),
276                                ["^Missing: 'key'$", "^oops$",
277                                 "^Missing: 'key'$",
278                                 "^Missing: 'key' : oops$"])
279
280    def testAssertMultiLineEqual(self):
281        self.assertMessages('assertMultiLineEqual', ("", "foo"),
282                            [r"\+ foo$", "^oops$",
283                             r"\+ foo$",
284                             r"\+ foo : oops$"])
285
286    def testAssertLess(self):
287        self.assertMessages('assertLess', (2, 1),
288                            ["^2 not less than 1$", "^oops$",
289                             "^2 not less than 1$", "^2 not less than 1 : oops$"])
290
291    def testAssertLessEqual(self):
292        self.assertMessages('assertLessEqual', (2, 1),
293                            ["^2 not less than or equal to 1$", "^oops$",
294                             "^2 not less than or equal to 1$",
295                             "^2 not less than or equal to 1 : oops$"])
296
297    def testAssertGreater(self):
298        self.assertMessages('assertGreater', (1, 2),
299                            ["^1 not greater than 2$", "^oops$",
300                             "^1 not greater than 2$",
301                             "^1 not greater than 2 : oops$"])
302
303    def testAssertGreaterEqual(self):
304        self.assertMessages('assertGreaterEqual', (1, 2),
305                            ["^1 not greater than or equal to 2$", "^oops$",
306                             "^1 not greater than or equal to 2$",
307                             "^1 not greater than or equal to 2 : oops$"])
308
309    def testAssertIsNone(self):
310        self.assertMessages('assertIsNone', ('not None',),
311                            ["^'not None' is not None$", "^oops$",
312                             "^'not None' is not None$",
313                             "^'not None' is not None : oops$"])
314
315    def testAssertIsNotNone(self):
316        self.assertMessages('assertIsNotNone', (None,),
317                            ["^unexpectedly None$", "^oops$",
318                             "^unexpectedly None$",
319                             "^unexpectedly None : oops$"])
320
321    def testAssertIs(self):
322        self.assertMessages('assertIs', (None, 'foo'),
323                            ["^None is not 'foo'$", "^oops$",
324                             "^None is not 'foo'$",
325                             "^None is not 'foo' : oops$"])
326
327    def testAssertIsNot(self):
328        self.assertMessages('assertIsNot', (None, None),
329                            ["^unexpectedly identical: None$", "^oops$",
330                             "^unexpectedly identical: None$",
331                             "^unexpectedly identical: None : oops$"])
332
333    def testAssertRegex(self):
334        self.assertMessages('assertRegex', ('foo', 'bar'),
335                            ["^Regex didn't match:",
336                             "^oops$",
337                             "^Regex didn't match:",
338                             "^Regex didn't match: (.*) : oops$"])
339
340    def testAssertNotRegex(self):
341        self.assertMessages('assertNotRegex', ('foo', 'foo'),
342                            ["^Regex matched:",
343                             "^oops$",
344                             "^Regex matched:",
345                             "^Regex matched: (.*) : oops$"])
346
347
348    def assertMessagesCM(self, methodName, args, func, errors):
349        """
350        Check that the correct error messages are raised while executing:
351          with method(*args):
352              func()
353        *errors* should be a list of 4 regex that match the error when:
354          1) longMessage = False and no msg passed;
355          2) longMessage = False and msg passed;
356          3) longMessage = True and no msg passed;
357          4) longMessage = True and msg passed;
358        """
359        p = product((self.testableFalse, self.testableTrue),
360                    ({}, {"msg": "oops"}))
361        for (cls, kwargs), err in zip(p, errors):
362            method = getattr(cls, methodName)
363            with self.assertRaisesRegex(cls.failureException, err):
364                with method(*args, **kwargs) as cm:
365                    func()
366
367    def testAssertRaises(self):
368        self.assertMessagesCM('assertRaises', (TypeError,), lambda: None,
369                              ['^TypeError not raised$', '^oops$',
370                               '^TypeError not raised$',
371                               '^TypeError not raised : oops$'])
372
373    def testAssertRaisesRegex(self):
374        # test error not raised
375        self.assertMessagesCM('assertRaisesRegex', (TypeError, 'unused regex'),
376                              lambda: None,
377                              ['^TypeError not raised$', '^oops$',
378                               '^TypeError not raised$',
379                               '^TypeError not raised : oops$'])
380        # test error raised but with wrong message
381        def raise_wrong_message():
382            raise TypeError('foo')
383        self.assertMessagesCM('assertRaisesRegex', (TypeError, 'regex'),
384                              raise_wrong_message,
385                              ['^"regex" does not match "foo"$', '^oops$',
386                               '^"regex" does not match "foo"$',
387                               '^"regex" does not match "foo" : oops$'])
388
389    def testAssertWarns(self):
390        self.assertMessagesCM('assertWarns', (UserWarning,), lambda: None,
391                              ['^UserWarning not triggered$', '^oops$',
392                               '^UserWarning not triggered$',
393                               '^UserWarning not triggered : oops$'])
394
395    def testAssertWarnsRegex(self):
396        # test error not raised
397        self.assertMessagesCM('assertWarnsRegex', (UserWarning, 'unused regex'),
398                              lambda: None,
399                              ['^UserWarning not triggered$', '^oops$',
400                               '^UserWarning not triggered$',
401                               '^UserWarning not triggered : oops$'])
402        # test warning raised but with wrong message
403        def raise_wrong_message():
404            warnings.warn('foo')
405        self.assertMessagesCM('assertWarnsRegex', (UserWarning, 'regex'),
406                              raise_wrong_message,
407                              ['^"regex" does not match "foo"$', '^oops$',
408                               '^"regex" does not match "foo"$',
409                               '^"regex" does not match "foo" : oops$'])
410
411
412if __name__ == "__main__":
413    unittest.main()
414