testtools: Merge in new upstream.
[samba.git] / lib / testtools / testtools / tests / test_matchers.py
1 # Copyright (c) 2008-2010 Jonathan M. Lange. See LICENSE for details.
2
3 """Tests for matchers."""
4
5 import doctest
6 import sys
7
8 from testtools import (
9     Matcher, # check that Matcher is exposed at the top level for docs.
10     TestCase,
11     )
12 from testtools.matchers import (
13     Annotate,
14     Equals,
15     DocTestMatches,
16     DoesNotEndWith,
17     DoesNotStartWith,
18     EndsWith,
19     KeysEqual,
20     Is,
21     LessThan,
22     MatchesAny,
23     MatchesAll,
24     MatchesException,
25     Mismatch,
26     Not,
27     NotEquals,
28     Raises,
29     raises,
30     StartsWith,
31     )
32
33 # Silence pyflakes.
34 Matcher
35
36
37 class TestMismatch(TestCase):
38
39     def test_constructor_arguments(self):
40         mismatch = Mismatch("some description", {'detail': "things"})
41         self.assertEqual("some description", mismatch.describe())
42         self.assertEqual({'detail': "things"}, mismatch.get_details())
43
44     def test_constructor_no_arguments(self):
45         mismatch = Mismatch()
46         self.assertThat(mismatch.describe,
47             Raises(MatchesException(NotImplementedError)))
48         self.assertEqual({}, mismatch.get_details())
49
50
51 class TestMatchersInterface(object):
52
53     def test_matches_match(self):
54         matcher = self.matches_matcher
55         matches = self.matches_matches
56         mismatches = self.matches_mismatches
57         for candidate in matches:
58             self.assertEqual(None, matcher.match(candidate))
59         for candidate in mismatches:
60             mismatch = matcher.match(candidate)
61             self.assertNotEqual(None, mismatch)
62             self.assertNotEqual(None, getattr(mismatch, 'describe', None))
63
64     def test__str__(self):
65         # [(expected, object to __str__)].
66         examples = self.str_examples
67         for expected, matcher in examples:
68             self.assertThat(matcher, DocTestMatches(expected))
69
70     def test_describe_difference(self):
71         # [(expected, matchee, matcher), ...]
72         examples = self.describe_examples
73         for difference, matchee, matcher in examples:
74             mismatch = matcher.match(matchee)
75             self.assertEqual(difference, mismatch.describe())
76
77     def test_mismatch_details(self):
78         # The mismatch object must provide get_details, which must return a
79         # dictionary mapping names to Content objects.
80         examples = self.describe_examples
81         for difference, matchee, matcher in examples:
82             mismatch = matcher.match(matchee)
83             details = mismatch.get_details()
84             self.assertEqual(dict(details), details)
85
86
87 class TestDocTestMatchesInterface(TestCase, TestMatchersInterface):
88
89     matches_matcher = DocTestMatches("Ran 1 test in ...s", doctest.ELLIPSIS)
90     matches_matches = ["Ran 1 test in 0.000s", "Ran 1 test in 1.234s"]
91     matches_mismatches = ["Ran 1 tests in 0.000s", "Ran 2 test in 0.000s"]
92
93     str_examples = [("DocTestMatches('Ran 1 test in ...s\\n')",
94         DocTestMatches("Ran 1 test in ...s")),
95         ("DocTestMatches('foo\\n', flags=8)", DocTestMatches("foo", flags=8)),
96         ]
97
98     describe_examples = [('Expected:\n    Ran 1 tests in ...s\nGot:\n'
99         '    Ran 1 test in 0.123s\n', "Ran 1 test in 0.123s",
100         DocTestMatches("Ran 1 tests in ...s", doctest.ELLIPSIS))]
101
102
103 class TestDocTestMatchesSpecific(TestCase):
104
105     def test___init__simple(self):
106         matcher = DocTestMatches("foo")
107         self.assertEqual("foo\n", matcher.want)
108
109     def test___init__flags(self):
110         matcher = DocTestMatches("bar\n", doctest.ELLIPSIS)
111         self.assertEqual("bar\n", matcher.want)
112         self.assertEqual(doctest.ELLIPSIS, matcher.flags)
113
114
115 class TestEqualsInterface(TestCase, TestMatchersInterface):
116
117     matches_matcher = Equals(1)
118     matches_matches = [1]
119     matches_mismatches = [2]
120
121     str_examples = [("Equals(1)", Equals(1)), ("Equals('1')", Equals('1'))]
122
123     describe_examples = [("1 != 2", 2, Equals(1))]
124
125
126 class TestNotEqualsInterface(TestCase, TestMatchersInterface):
127
128     matches_matcher = NotEquals(1)
129     matches_matches = [2]
130     matches_mismatches = [1]
131
132     str_examples = [
133         ("NotEquals(1)", NotEquals(1)), ("NotEquals('1')", NotEquals('1'))]
134
135     describe_examples = [("1 == 1", 1, NotEquals(1))]
136
137
138 class TestIsInterface(TestCase, TestMatchersInterface):
139
140     foo = object()
141     bar = object()
142
143     matches_matcher = Is(foo)
144     matches_matches = [foo]
145     matches_mismatches = [bar, 1]
146
147     str_examples = [("Is(2)", Is(2))]
148
149     describe_examples = [("1 is not 2", 2, Is(1))]
150
151
152 class TestLessThanInterface(TestCase, TestMatchersInterface):
153
154     matches_matcher = LessThan(4)
155     matches_matches = [-5, 3]
156     matches_mismatches = [4, 5, 5000]
157
158     str_examples = [
159         ("LessThan(12)", LessThan(12)),
160         ]
161
162     describe_examples = [('4 is >= 4', 4, LessThan(4))]
163
164
165 def make_error(type, *args, **kwargs):
166     try:
167         raise type(*args, **kwargs)
168     except type:
169         return sys.exc_info()
170
171
172 class TestMatchesExceptionInstanceInterface(TestCase, TestMatchersInterface):
173
174     matches_matcher = MatchesException(ValueError("foo"))
175     error_foo = make_error(ValueError, 'foo')
176     error_bar = make_error(ValueError, 'bar')
177     error_base_foo = make_error(Exception, 'foo')
178     matches_matches = [error_foo]
179     matches_mismatches = [error_bar, error_base_foo]
180
181     str_examples = [
182         ("MatchesException(Exception('foo',))",
183          MatchesException(Exception('foo')))
184         ]
185     describe_examples = [
186         ("%r is not a %r" % (Exception, ValueError),
187          error_base_foo,
188          MatchesException(ValueError("foo"))),
189         ("ValueError('bar',) has different arguments to ValueError('foo',).",
190          error_bar,
191          MatchesException(ValueError("foo"))),
192         ]
193
194
195 class TestMatchesExceptionTypeInterface(TestCase, TestMatchersInterface):
196
197     matches_matcher = MatchesException(ValueError)
198     error_foo = make_error(ValueError, 'foo')
199     error_sub = make_error(UnicodeError, 'bar')
200     error_base_foo = make_error(Exception, 'foo')
201     matches_matches = [error_foo, error_sub]
202     matches_mismatches = [error_base_foo]
203
204     str_examples = [
205         ("MatchesException(%r)" % Exception,
206          MatchesException(Exception))
207         ]
208     describe_examples = [
209         ("%r is not a %r" % (Exception, ValueError),
210          error_base_foo,
211          MatchesException(ValueError)),
212         ]
213
214
215 class TestNotInterface(TestCase, TestMatchersInterface):
216
217     matches_matcher = Not(Equals(1))
218     matches_matches = [2]
219     matches_mismatches = [1]
220
221     str_examples = [
222         ("Not(Equals(1))", Not(Equals(1))),
223         ("Not(Equals('1'))", Not(Equals('1')))]
224
225     describe_examples = [('1 matches Equals(1)', 1, Not(Equals(1)))]
226
227
228 class TestMatchersAnyInterface(TestCase, TestMatchersInterface):
229
230     matches_matcher = MatchesAny(DocTestMatches("1"), DocTestMatches("2"))
231     matches_matches = ["1", "2"]
232     matches_mismatches = ["3"]
233
234     str_examples = [(
235         "MatchesAny(DocTestMatches('1\\n'), DocTestMatches('2\\n'))",
236         MatchesAny(DocTestMatches("1"), DocTestMatches("2"))),
237         ]
238
239     describe_examples = [("""Differences: [
240 Expected:
241     1
242 Got:
243     3
244
245 Expected:
246     2
247 Got:
248     3
249
250 ]""",
251         "3", MatchesAny(DocTestMatches("1"), DocTestMatches("2")))]
252
253
254 class TestMatchesAllInterface(TestCase, TestMatchersInterface):
255
256     matches_matcher = MatchesAll(NotEquals(1), NotEquals(2))
257     matches_matches = [3, 4]
258     matches_mismatches = [1, 2]
259
260     str_examples = [
261         ("MatchesAll(NotEquals(1), NotEquals(2))",
262          MatchesAll(NotEquals(1), NotEquals(2)))]
263
264     describe_examples = [("""Differences: [
265 1 == 1
266 ]""",
267                           1, MatchesAll(NotEquals(1), NotEquals(2)))]
268
269
270 class TestKeysEqual(TestCase, TestMatchersInterface):
271
272     matches_matcher = KeysEqual('foo', 'bar')
273     matches_matches = [
274         {'foo': 0, 'bar': 1},
275         ]
276     matches_mismatches = [
277         {},
278         {'foo': 0},
279         {'bar': 1},
280         {'foo': 0, 'bar': 1, 'baz': 2},
281         {'a': None, 'b': None, 'c': None},
282         ]
283
284     str_examples = [
285         ("KeysEqual('foo', 'bar')", KeysEqual('foo', 'bar')),
286         ]
287
288     describe_examples = [
289         ("['bar', 'foo'] does not match {'baz': 2, 'foo': 0, 'bar': 1}: "
290          "Keys not equal",
291          {'foo': 0, 'bar': 1, 'baz': 2}, KeysEqual('foo', 'bar')),
292         ]
293
294
295 class TestAnnotate(TestCase, TestMatchersInterface):
296
297     matches_matcher = Annotate("foo", Equals(1))
298     matches_matches = [1]
299     matches_mismatches = [2]
300
301     str_examples = [
302         ("Annotate('foo', Equals(1))", Annotate("foo", Equals(1)))]
303
304     describe_examples = [("1 != 2: foo", 2, Annotate('foo', Equals(1)))]
305
306
307 class TestRaisesInterface(TestCase, TestMatchersInterface):
308
309     matches_matcher = Raises()
310     def boom():
311         raise Exception('foo')
312     matches_matches = [boom]
313     matches_mismatches = [lambda:None]
314
315     # Tricky to get function objects to render constantly, and the interfaces
316     # helper uses assertEqual rather than (for instance) DocTestMatches.
317     str_examples = []
318
319     describe_examples = []
320
321
322 class TestRaisesExceptionMatcherInterface(TestCase, TestMatchersInterface):
323
324     matches_matcher = Raises(
325         exception_matcher=MatchesException(Exception('foo')))
326     def boom_bar():
327         raise Exception('bar')
328     def boom_foo():
329         raise Exception('foo')
330     matches_matches = [boom_foo]
331     matches_mismatches = [lambda:None, boom_bar]
332
333     # Tricky to get function objects to render constantly, and the interfaces
334     # helper uses assertEqual rather than (for instance) DocTestMatches.
335     str_examples = []
336
337     describe_examples = []
338
339
340 class TestRaisesBaseTypes(TestCase):
341
342     def raiser(self):
343         raise KeyboardInterrupt('foo')
344
345     def test_KeyboardInterrupt_matched(self):
346         # When KeyboardInterrupt is matched, it is swallowed.
347         matcher = Raises(MatchesException(KeyboardInterrupt))
348         self.assertThat(self.raiser, matcher)
349
350     def test_KeyboardInterrupt_propogates(self):
351         # The default 'it raised' propogates KeyboardInterrupt.
352         match_keyb = Raises(MatchesException(KeyboardInterrupt))
353         def raise_keyb_from_match():
354             matcher = Raises()
355             matcher.match(self.raiser)
356         self.assertThat(raise_keyb_from_match, match_keyb)
357
358     def test_KeyboardInterrupt_match_Exception_propogates(self):
359         # If the raised exception isn't matched, and it is not a subclass of
360         # Exception, it is propogated.
361         match_keyb = Raises(MatchesException(KeyboardInterrupt))
362         def raise_keyb_from_match():
363             if sys.version_info > (2, 5):
364                 matcher = Raises(MatchesException(Exception))
365             else:
366                 # On Python 2.4 KeyboardInterrupt is a StandardError subclass
367                 # but should propogate from less generic exception matchers
368                 matcher = Raises(MatchesException(EnvironmentError))
369             matcher.match(self.raiser)
370         self.assertThat(raise_keyb_from_match, match_keyb)
371
372
373 class TestRaisesConvenience(TestCase):
374
375     def test_exc_type(self):
376         self.assertThat(lambda: 1/0, raises(ZeroDivisionError))
377
378     def test_exc_value(self):
379         e = RuntimeError("You lose!")
380         def raiser():
381             raise e
382         self.assertThat(raiser, raises(e))
383
384
385 class DoesNotStartWithTests(TestCase):
386
387     def test_describe(self):
388         mismatch = DoesNotStartWith("fo", "bo")
389         self.assertEqual("'fo' does not start with 'bo'.", mismatch.describe())
390
391
392 class StartsWithTests(TestCase):
393
394     def test_str(self):
395         matcher = StartsWith("bar")
396         self.assertEqual("Starts with 'bar'.", str(matcher))
397
398     def test_match(self):
399         matcher = StartsWith("bar")
400         self.assertIs(None, matcher.match("barf"))
401
402     def test_mismatch_returns_does_not_start_with(self):
403         matcher = StartsWith("bar")
404         self.assertIsInstance(matcher.match("foo"), DoesNotStartWith)
405
406     def test_mismatch_sets_matchee(self):
407         matcher = StartsWith("bar")
408         mismatch = matcher.match("foo")
409         self.assertEqual("foo", mismatch.matchee)
410
411     def test_mismatch_sets_expected(self):
412         matcher = StartsWith("bar")
413         mismatch = matcher.match("foo")
414         self.assertEqual("bar", mismatch.expected)
415
416
417 class DoesNotEndWithTests(TestCase):
418
419     def test_describe(self):
420         mismatch = DoesNotEndWith("fo", "bo")
421         self.assertEqual("'fo' does not end with 'bo'.", mismatch.describe())
422
423
424 class EndsWithTests(TestCase):
425
426     def test_str(self):
427         matcher = EndsWith("bar")
428         self.assertEqual("Ends with 'bar'.", str(matcher))
429
430     def test_match(self):
431         matcher = EndsWith("arf")
432         self.assertIs(None, matcher.match("barf"))
433
434     def test_mismatch_returns_does_not_end_with(self):
435         matcher = EndsWith("bar")
436         self.assertIsInstance(matcher.match("foo"), DoesNotEndWith)
437
438     def test_mismatch_sets_matchee(self):
439         matcher = EndsWith("bar")
440         mismatch = matcher.match("foo")
441         self.assertEqual("foo", mismatch.matchee)
442
443     def test_mismatch_sets_expected(self):
444         matcher = EndsWith("bar")
445         mismatch = matcher.match("foo")
446         self.assertEqual("bar", mismatch.expected)
447
448
449 def test_suite():
450     from unittest import TestLoader
451     return TestLoader().loadTestsFromName(__name__)