testtools: Import new upstream snapshot.
[nivanova/samba-autobuild/.git] / lib / testtools / testtools / tests / test_matchers.py
1 # Copyright (c) 2008-2011 testtools developers. See LICENSE for details.
2
3 """Tests for matchers."""
4
5 import doctest
6 import re
7 import sys
8
9 from testtools import (
10     Matcher, # check that Matcher is exposed at the top level for docs.
11     TestCase,
12     )
13 from testtools.compat import (
14     StringIO,
15     str_is_unicode,
16     text_repr,
17     _b,
18     _u,
19     )
20 from testtools.matchers import (
21     AfterPreprocessing,
22     AllMatch,
23     Annotate,
24     AnnotatedMismatch,
25     _BinaryMismatch,
26     Contains,
27     Equals,
28     DocTestMatches,
29     DoesNotEndWith,
30     DoesNotStartWith,
31     EndsWith,
32     KeysEqual,
33     Is,
34     IsInstance,
35     LessThan,
36     GreaterThan,
37     MatchesAny,
38     MatchesAll,
39     MatchesException,
40     MatchesListwise,
41     MatchesRegex,
42     MatchesSetwise,
43     MatchesStructure,
44     Mismatch,
45     MismatchDecorator,
46     MismatchError,
47     Not,
48     NotEquals,
49     Raises,
50     raises,
51     StartsWith,
52     )
53 from testtools.tests.helpers import FullStackRunTest
54
55 # Silence pyflakes.
56 Matcher
57
58
59 class TestMismatch(TestCase):
60
61     run_tests_with = FullStackRunTest
62
63     def test_constructor_arguments(self):
64         mismatch = Mismatch("some description", {'detail': "things"})
65         self.assertEqual("some description", mismatch.describe())
66         self.assertEqual({'detail': "things"}, mismatch.get_details())
67
68     def test_constructor_no_arguments(self):
69         mismatch = Mismatch()
70         self.assertThat(mismatch.describe,
71             Raises(MatchesException(NotImplementedError)))
72         self.assertEqual({}, mismatch.get_details())
73
74
75 class TestMismatchError(TestCase):
76
77     def test_is_assertion_error(self):
78         # MismatchError is an AssertionError, so that most of the time, it
79         # looks like a test failure, rather than an error.
80         def raise_mismatch_error():
81             raise MismatchError(2, Equals(3), Equals(3).match(2))
82         self.assertRaises(AssertionError, raise_mismatch_error)
83
84     def test_default_description_is_mismatch(self):
85         mismatch = Equals(3).match(2)
86         e = MismatchError(2, Equals(3), mismatch)
87         self.assertEqual(mismatch.describe(), str(e))
88
89     def test_default_description_unicode(self):
90         matchee = _u('\xa7')
91         matcher = Equals(_u('a'))
92         mismatch = matcher.match(matchee)
93         e = MismatchError(matchee, matcher, mismatch)
94         self.assertEqual(mismatch.describe(), str(e))
95
96     def test_verbose_description(self):
97         matchee = 2
98         matcher = Equals(3)
99         mismatch = matcher.match(2)
100         e = MismatchError(matchee, matcher, mismatch, True)
101         expected = (
102             'Match failed. Matchee: %r\n'
103             'Matcher: %s\n'
104             'Difference: %s\n' % (
105                 matchee,
106                 matcher,
107                 matcher.match(matchee).describe(),
108                 ))
109         self.assertEqual(expected, str(e))
110
111     def test_verbose_unicode(self):
112         # When assertThat is given matchees or matchers that contain non-ASCII
113         # unicode strings, we can still provide a meaningful error.
114         matchee = _u('\xa7')
115         matcher = Equals(_u('a'))
116         mismatch = matcher.match(matchee)
117         expected = (
118             'Match failed. Matchee: %s\n'
119             'Matcher: %s\n'
120             'Difference: %s\n' % (
121                 text_repr(matchee),
122                 matcher,
123                 mismatch.describe(),
124                 ))
125         e = MismatchError(matchee, matcher, mismatch, True)
126         if str_is_unicode:
127             actual = str(e)
128         else:
129             actual = unicode(e)
130             # Using str() should still work, and return ascii only
131             self.assertEqual(
132                 expected.replace(matchee, matchee.encode("unicode-escape")),
133                 str(e).decode("ascii"))
134         self.assertEqual(expected, actual)
135
136
137 class Test_BinaryMismatch(TestCase):
138     """Mismatches from binary comparisons need useful describe output"""
139
140     _long_string = "This is a longish multiline non-ascii string\n\xa7"
141     _long_b = _b(_long_string)
142     _long_u = _u(_long_string)
143
144     def test_short_objects(self):
145         o1, o2 = object(), object()
146         mismatch = _BinaryMismatch(o1, "!~", o2)
147         self.assertEqual(mismatch.describe(), "%r !~ %r" % (o1, o2))
148
149     def test_short_mixed_strings(self):
150         b, u = _b("\xa7"), _u("\xa7")
151         mismatch = _BinaryMismatch(b, "!~", u)
152         self.assertEqual(mismatch.describe(), "%r !~ %r" % (b, u))
153
154     def test_long_bytes(self):
155         one_line_b = self._long_b.replace(_b("\n"), _b(" "))
156         mismatch = _BinaryMismatch(one_line_b, "!~", self._long_b)
157         self.assertEqual(mismatch.describe(),
158             "%s:\nreference = %s\nactual    = %s\n" % ("!~",
159                 text_repr(one_line_b),
160                 text_repr(self._long_b, multiline=True)))
161
162     def test_long_unicode(self):
163         one_line_u = self._long_u.replace("\n", " ")
164         mismatch = _BinaryMismatch(one_line_u, "!~", self._long_u)
165         self.assertEqual(mismatch.describe(),
166             "%s:\nreference = %s\nactual    = %s\n" % ("!~",
167                 text_repr(one_line_u),
168                 text_repr(self._long_u, multiline=True)))
169
170     def test_long_mixed_strings(self):
171         mismatch = _BinaryMismatch(self._long_b, "!~", self._long_u)
172         self.assertEqual(mismatch.describe(),
173             "%s:\nreference = %s\nactual    = %s\n" % ("!~",
174                 text_repr(self._long_b, multiline=True),
175                 text_repr(self._long_u, multiline=True)))
176
177     def test_long_bytes_and_object(self):
178         obj = object()
179         mismatch = _BinaryMismatch(self._long_b, "!~", obj)
180         self.assertEqual(mismatch.describe(),
181             "%s:\nreference = %s\nactual    = %s\n" % ("!~",
182                 text_repr(self._long_b, multiline=True),
183                 repr(obj)))
184
185     def test_long_unicode_and_object(self):
186         obj = object()
187         mismatch = _BinaryMismatch(self._long_u, "!~", obj)
188         self.assertEqual(mismatch.describe(),
189             "%s:\nreference = %s\nactual    = %s\n" % ("!~",
190                 text_repr(self._long_u, multiline=True),
191                 repr(obj)))
192
193
194 class TestMatchersInterface(object):
195
196     run_tests_with = FullStackRunTest
197
198     def test_matches_match(self):
199         matcher = self.matches_matcher
200         matches = self.matches_matches
201         mismatches = self.matches_mismatches
202         for candidate in matches:
203             self.assertEqual(None, matcher.match(candidate))
204         for candidate in mismatches:
205             mismatch = matcher.match(candidate)
206             self.assertNotEqual(None, mismatch)
207             self.assertNotEqual(None, getattr(mismatch, 'describe', None))
208
209     def test__str__(self):
210         # [(expected, object to __str__)].
211         examples = self.str_examples
212         for expected, matcher in examples:
213             self.assertThat(matcher, DocTestMatches(expected))
214
215     def test_describe_difference(self):
216         # [(expected, matchee, matcher), ...]
217         examples = self.describe_examples
218         for difference, matchee, matcher in examples:
219             mismatch = matcher.match(matchee)
220             self.assertEqual(difference, mismatch.describe())
221
222     def test_mismatch_details(self):
223         # The mismatch object must provide get_details, which must return a
224         # dictionary mapping names to Content objects.
225         examples = self.describe_examples
226         for difference, matchee, matcher in examples:
227             mismatch = matcher.match(matchee)
228             details = mismatch.get_details()
229             self.assertEqual(dict(details), details)
230
231
232 class TestDocTestMatchesInterface(TestCase, TestMatchersInterface):
233
234     matches_matcher = DocTestMatches("Ran 1 test in ...s", doctest.ELLIPSIS)
235     matches_matches = ["Ran 1 test in 0.000s", "Ran 1 test in 1.234s"]
236     matches_mismatches = ["Ran 1 tests in 0.000s", "Ran 2 test in 0.000s"]
237
238     str_examples = [("DocTestMatches('Ran 1 test in ...s\\n')",
239         DocTestMatches("Ran 1 test in ...s")),
240         ("DocTestMatches('foo\\n', flags=8)", DocTestMatches("foo", flags=8)),
241         ]
242
243     describe_examples = [('Expected:\n    Ran 1 tests in ...s\nGot:\n'
244         '    Ran 1 test in 0.123s\n', "Ran 1 test in 0.123s",
245         DocTestMatches("Ran 1 tests in ...s", doctest.ELLIPSIS))]
246
247
248 class TestDocTestMatchesInterfaceUnicode(TestCase, TestMatchersInterface):
249
250     matches_matcher = DocTestMatches(_u("\xa7..."), doctest.ELLIPSIS)
251     matches_matches = [_u("\xa7"), _u("\xa7 more\n")]
252     matches_mismatches = ["\\xa7", _u("more \xa7"), _u("\n\xa7")]
253
254     str_examples = [("DocTestMatches(%r)" % (_u("\xa7\n"),),
255         DocTestMatches(_u("\xa7"))),
256         ]
257
258     describe_examples = [(
259         _u("Expected:\n    \xa7\nGot:\n    a\n"),
260         "a",
261         DocTestMatches(_u("\xa7"), doctest.ELLIPSIS))]
262
263
264 class TestDocTestMatchesSpecific(TestCase):
265
266     run_tests_with = FullStackRunTest
267
268     def test___init__simple(self):
269         matcher = DocTestMatches("foo")
270         self.assertEqual("foo\n", matcher.want)
271
272     def test___init__flags(self):
273         matcher = DocTestMatches("bar\n", doctest.ELLIPSIS)
274         self.assertEqual("bar\n", matcher.want)
275         self.assertEqual(doctest.ELLIPSIS, matcher.flags)
276
277     def test_describe_non_ascii_bytes(self):
278         """Even with bytestrings, the mismatch should be coercible to unicode
279
280         DocTestMatches is intended for text, but the Python 2 str type also
281         permits arbitrary binary inputs. This is a slightly bogus thing to do,
282         and under Python 3 using bytes objects will reasonably raise an error.
283         """
284         header = _b("\x89PNG\r\n\x1a\n...")
285         if str_is_unicode:
286             self.assertRaises(TypeError,
287                 DocTestMatches, header, doctest.ELLIPSIS)
288             return
289         matcher = DocTestMatches(header, doctest.ELLIPSIS)
290         mismatch = matcher.match(_b("GIF89a\1\0\1\0\0\0\0;"))
291         # Must be treatable as unicode text, the exact output matters less
292         self.assertTrue(unicode(mismatch.describe()))
293
294
295 class TestEqualsInterface(TestCase, TestMatchersInterface):
296
297     matches_matcher = Equals(1)
298     matches_matches = [1]
299     matches_mismatches = [2]
300
301     str_examples = [("Equals(1)", Equals(1)), ("Equals('1')", Equals('1'))]
302
303     describe_examples = [("1 != 2", 2, Equals(1))]
304
305
306 class TestNotEqualsInterface(TestCase, TestMatchersInterface):
307
308     matches_matcher = NotEquals(1)
309     matches_matches = [2]
310     matches_mismatches = [1]
311
312     str_examples = [
313         ("NotEquals(1)", NotEquals(1)), ("NotEquals('1')", NotEquals('1'))]
314
315     describe_examples = [("1 == 1", 1, NotEquals(1))]
316
317
318 class TestIsInterface(TestCase, TestMatchersInterface):
319
320     foo = object()
321     bar = object()
322
323     matches_matcher = Is(foo)
324     matches_matches = [foo]
325     matches_mismatches = [bar, 1]
326
327     str_examples = [("Is(2)", Is(2))]
328
329     describe_examples = [("1 is not 2", 2, Is(1))]
330
331
332 class TestIsInstanceInterface(TestCase, TestMatchersInterface):
333
334     class Foo:pass
335
336     matches_matcher = IsInstance(Foo)
337     matches_matches = [Foo()]
338     matches_mismatches = [object(), 1, Foo]
339
340     str_examples = [
341             ("IsInstance(str)", IsInstance(str)),
342             ("IsInstance(str, int)", IsInstance(str, int)),
343             ]
344
345     describe_examples = [
346             ("'foo' is not an instance of int", 'foo', IsInstance(int)),
347             ("'foo' is not an instance of any of (int, type)", 'foo',
348              IsInstance(int, type)),
349             ]
350
351
352 class TestLessThanInterface(TestCase, TestMatchersInterface):
353
354     matches_matcher = LessThan(4)
355     matches_matches = [-5, 3]
356     matches_mismatches = [4, 5, 5000]
357
358     str_examples = [
359         ("LessThan(12)", LessThan(12)),
360         ]
361
362     describe_examples = [
363         ('4 is not > 5', 5, LessThan(4)),
364         ('4 is not > 4', 4, LessThan(4)),
365         ]
366
367
368 class TestGreaterThanInterface(TestCase, TestMatchersInterface):
369
370     matches_matcher = GreaterThan(4)
371     matches_matches = [5, 8]
372     matches_mismatches = [-2, 0, 4]
373
374     str_examples = [
375         ("GreaterThan(12)", GreaterThan(12)),
376         ]
377
378     describe_examples = [
379         ('5 is not < 4', 4, GreaterThan(5)),
380         ('4 is not < 4', 4, GreaterThan(4)),
381         ]
382
383
384 class TestContainsInterface(TestCase, TestMatchersInterface):
385
386     matches_matcher = Contains('foo')
387     matches_matches = ['foo', 'afoo', 'fooa']
388     matches_mismatches = ['f', 'fo', 'oo', 'faoo', 'foao']
389
390     str_examples = [
391         ("Contains(1)", Contains(1)),
392         ("Contains('foo')", Contains('foo')),
393         ]
394
395     describe_examples = [("1 not in 2", 2, Contains(1))]
396
397
398 def make_error(type, *args, **kwargs):
399     try:
400         raise type(*args, **kwargs)
401     except type:
402         return sys.exc_info()
403
404
405 class TestMatchesExceptionInstanceInterface(TestCase, TestMatchersInterface):
406
407     matches_matcher = MatchesException(ValueError("foo"))
408     error_foo = make_error(ValueError, 'foo')
409     error_bar = make_error(ValueError, 'bar')
410     error_base_foo = make_error(Exception, 'foo')
411     matches_matches = [error_foo]
412     matches_mismatches = [error_bar, error_base_foo]
413
414     str_examples = [
415         ("MatchesException(Exception('foo',))",
416          MatchesException(Exception('foo')))
417         ]
418     describe_examples = [
419         ("%r is not a %r" % (Exception, ValueError),
420          error_base_foo,
421          MatchesException(ValueError("foo"))),
422         ("ValueError('bar',) has different arguments to ValueError('foo',).",
423          error_bar,
424          MatchesException(ValueError("foo"))),
425         ]
426
427
428 class TestMatchesExceptionTypeInterface(TestCase, TestMatchersInterface):
429
430     matches_matcher = MatchesException(ValueError)
431     error_foo = make_error(ValueError, 'foo')
432     error_sub = make_error(UnicodeError, 'bar')
433     error_base_foo = make_error(Exception, 'foo')
434     matches_matches = [error_foo, error_sub]
435     matches_mismatches = [error_base_foo]
436
437     str_examples = [
438         ("MatchesException(%r)" % Exception,
439          MatchesException(Exception))
440         ]
441     describe_examples = [
442         ("%r is not a %r" % (Exception, ValueError),
443          error_base_foo,
444          MatchesException(ValueError)),
445         ]
446
447
448 class TestMatchesExceptionTypeReInterface(TestCase, TestMatchersInterface):
449
450     matches_matcher = MatchesException(ValueError, 'fo.')
451     error_foo = make_error(ValueError, 'foo')
452     error_sub = make_error(UnicodeError, 'foo')
453     error_bar = make_error(ValueError, 'bar')
454     matches_matches = [error_foo, error_sub]
455     matches_mismatches = [error_bar]
456
457     str_examples = [
458         ("MatchesException(%r)" % Exception,
459          MatchesException(Exception, 'fo.'))
460         ]
461     describe_examples = [
462         ("'bar' does not match /fo./",
463          error_bar, MatchesException(ValueError, "fo.")),
464         ]
465
466
467 class TestMatchesExceptionTypeMatcherInterface(TestCase, TestMatchersInterface):
468
469     matches_matcher = MatchesException(
470         ValueError, AfterPreprocessing(str, Equals('foo')))
471     error_foo = make_error(ValueError, 'foo')
472     error_sub = make_error(UnicodeError, 'foo')
473     error_bar = make_error(ValueError, 'bar')
474     matches_matches = [error_foo, error_sub]
475     matches_mismatches = [error_bar]
476
477     str_examples = [
478         ("MatchesException(%r)" % Exception,
479          MatchesException(Exception, Equals('foo')))
480         ]
481     describe_examples = [
482         ("5 != %r" % (error_bar[1],),
483          error_bar, MatchesException(ValueError, Equals(5))),
484         ]
485
486
487 class TestNotInterface(TestCase, TestMatchersInterface):
488
489     matches_matcher = Not(Equals(1))
490     matches_matches = [2]
491     matches_mismatches = [1]
492
493     str_examples = [
494         ("Not(Equals(1))", Not(Equals(1))),
495         ("Not(Equals('1'))", Not(Equals('1')))]
496
497     describe_examples = [('1 matches Equals(1)', 1, Not(Equals(1)))]
498
499
500 class TestMatchersAnyInterface(TestCase, TestMatchersInterface):
501
502     matches_matcher = MatchesAny(DocTestMatches("1"), DocTestMatches("2"))
503     matches_matches = ["1", "2"]
504     matches_mismatches = ["3"]
505
506     str_examples = [(
507         "MatchesAny(DocTestMatches('1\\n'), DocTestMatches('2\\n'))",
508         MatchesAny(DocTestMatches("1"), DocTestMatches("2"))),
509         ]
510
511     describe_examples = [("""Differences: [
512 Expected:
513     1
514 Got:
515     3
516
517 Expected:
518     2
519 Got:
520     3
521
522 ]""",
523         "3", MatchesAny(DocTestMatches("1"), DocTestMatches("2")))]
524
525
526 class TestMatchesAllInterface(TestCase, TestMatchersInterface):
527
528     matches_matcher = MatchesAll(NotEquals(1), NotEquals(2))
529     matches_matches = [3, 4]
530     matches_mismatches = [1, 2]
531
532     str_examples = [
533         ("MatchesAll(NotEquals(1), NotEquals(2))",
534          MatchesAll(NotEquals(1), NotEquals(2)))]
535
536     describe_examples = [("""Differences: [
537 1 == 1
538 ]""",
539                           1, MatchesAll(NotEquals(1), NotEquals(2)))]
540
541
542 class TestKeysEqual(TestCase, TestMatchersInterface):
543
544     matches_matcher = KeysEqual('foo', 'bar')
545     matches_matches = [
546         {'foo': 0, 'bar': 1},
547         ]
548     matches_mismatches = [
549         {},
550         {'foo': 0},
551         {'bar': 1},
552         {'foo': 0, 'bar': 1, 'baz': 2},
553         {'a': None, 'b': None, 'c': None},
554         ]
555
556     str_examples = [
557         ("KeysEqual('foo', 'bar')", KeysEqual('foo', 'bar')),
558         ]
559
560     describe_examples = [
561         ("['bar', 'foo'] does not match {'baz': 2, 'foo': 0, 'bar': 1}: "
562          "Keys not equal",
563          {'foo': 0, 'bar': 1, 'baz': 2}, KeysEqual('foo', 'bar')),
564         ]
565
566
567 class TestAnnotate(TestCase, TestMatchersInterface):
568
569     matches_matcher = Annotate("foo", Equals(1))
570     matches_matches = [1]
571     matches_mismatches = [2]
572
573     str_examples = [
574         ("Annotate('foo', Equals(1))", Annotate("foo", Equals(1)))]
575
576     describe_examples = [("1 != 2: foo", 2, Annotate('foo', Equals(1)))]
577
578     def test_if_message_no_message(self):
579         # Annotate.if_message returns the given matcher if there is no
580         # message.
581         matcher = Equals(1)
582         not_annotated = Annotate.if_message('', matcher)
583         self.assertIs(matcher, not_annotated)
584
585     def test_if_message_given_message(self):
586         # Annotate.if_message returns an annotated version of the matcher if a
587         # message is provided.
588         matcher = Equals(1)
589         expected = Annotate('foo', matcher)
590         annotated = Annotate.if_message('foo', matcher)
591         self.assertThat(
592             annotated,
593             MatchesStructure.fromExample(expected, 'annotation', 'matcher'))
594
595
596 class TestAnnotatedMismatch(TestCase):
597
598     run_tests_with = FullStackRunTest
599
600     def test_forwards_details(self):
601         x = Mismatch('description', {'foo': 'bar'})
602         annotated = AnnotatedMismatch("annotation", x)
603         self.assertEqual(x.get_details(), annotated.get_details())
604
605
606 class TestRaisesInterface(TestCase, TestMatchersInterface):
607
608     matches_matcher = Raises()
609     def boom():
610         raise Exception('foo')
611     matches_matches = [boom]
612     matches_mismatches = [lambda:None]
613
614     # Tricky to get function objects to render constantly, and the interfaces
615     # helper uses assertEqual rather than (for instance) DocTestMatches.
616     str_examples = []
617
618     describe_examples = []
619
620
621 class TestRaisesExceptionMatcherInterface(TestCase, TestMatchersInterface):
622
623     matches_matcher = Raises(
624         exception_matcher=MatchesException(Exception('foo')))
625     def boom_bar():
626         raise Exception('bar')
627     def boom_foo():
628         raise Exception('foo')
629     matches_matches = [boom_foo]
630     matches_mismatches = [lambda:None, boom_bar]
631
632     # Tricky to get function objects to render constantly, and the interfaces
633     # helper uses assertEqual rather than (for instance) DocTestMatches.
634     str_examples = []
635
636     describe_examples = []
637
638
639 class TestRaisesBaseTypes(TestCase):
640
641     run_tests_with = FullStackRunTest
642
643     def raiser(self):
644         raise KeyboardInterrupt('foo')
645
646     def test_KeyboardInterrupt_matched(self):
647         # When KeyboardInterrupt is matched, it is swallowed.
648         matcher = Raises(MatchesException(KeyboardInterrupt))
649         self.assertThat(self.raiser, matcher)
650
651     def test_KeyboardInterrupt_propogates(self):
652         # The default 'it raised' propogates KeyboardInterrupt.
653         match_keyb = Raises(MatchesException(KeyboardInterrupt))
654         def raise_keyb_from_match():
655             matcher = Raises()
656             matcher.match(self.raiser)
657         self.assertThat(raise_keyb_from_match, match_keyb)
658
659     def test_KeyboardInterrupt_match_Exception_propogates(self):
660         # If the raised exception isn't matched, and it is not a subclass of
661         # Exception, it is propogated.
662         match_keyb = Raises(MatchesException(KeyboardInterrupt))
663         def raise_keyb_from_match():
664             if sys.version_info > (2, 5):
665                 matcher = Raises(MatchesException(Exception))
666             else:
667                 # On Python 2.4 KeyboardInterrupt is a StandardError subclass
668                 # but should propogate from less generic exception matchers
669                 matcher = Raises(MatchesException(EnvironmentError))
670             matcher.match(self.raiser)
671         self.assertThat(raise_keyb_from_match, match_keyb)
672
673
674 class TestRaisesConvenience(TestCase):
675
676     run_tests_with = FullStackRunTest
677
678     def test_exc_type(self):
679         self.assertThat(lambda: 1/0, raises(ZeroDivisionError))
680
681     def test_exc_value(self):
682         e = RuntimeError("You lose!")
683         def raiser():
684             raise e
685         self.assertThat(raiser, raises(e))
686
687
688 class DoesNotStartWithTests(TestCase):
689
690     run_tests_with = FullStackRunTest
691
692     def test_describe(self):
693         mismatch = DoesNotStartWith("fo", "bo")
694         self.assertEqual("'fo' does not start with 'bo'.", mismatch.describe())
695
696     def test_describe_non_ascii_unicode(self):
697         string = _u("A\xA7")
698         suffix = _u("B\xA7")
699         mismatch = DoesNotStartWith(string, suffix)
700         self.assertEqual("%s does not start with %s." % (
701             text_repr(string), text_repr(suffix)),
702             mismatch.describe())
703
704     def test_describe_non_ascii_bytes(self):
705         string = _b("A\xA7")
706         suffix = _b("B\xA7")
707         mismatch = DoesNotStartWith(string, suffix)
708         self.assertEqual("%r does not start with %r." % (string, suffix),
709             mismatch.describe())
710
711
712 class StartsWithTests(TestCase):
713
714     run_tests_with = FullStackRunTest
715
716     def test_str(self):
717         matcher = StartsWith("bar")
718         self.assertEqual("StartsWith('bar')", str(matcher))
719
720     def test_str_with_bytes(self):
721         b = _b("\xA7")
722         matcher = StartsWith(b)
723         self.assertEqual("StartsWith(%r)" % (b,), str(matcher))
724
725     def test_str_with_unicode(self):
726         u = _u("\xA7")
727         matcher = StartsWith(u)
728         self.assertEqual("StartsWith(%r)" % (u,), str(matcher))
729
730     def test_match(self):
731         matcher = StartsWith("bar")
732         self.assertIs(None, matcher.match("barf"))
733
734     def test_mismatch_returns_does_not_start_with(self):
735         matcher = StartsWith("bar")
736         self.assertIsInstance(matcher.match("foo"), DoesNotStartWith)
737
738     def test_mismatch_sets_matchee(self):
739         matcher = StartsWith("bar")
740         mismatch = matcher.match("foo")
741         self.assertEqual("foo", mismatch.matchee)
742
743     def test_mismatch_sets_expected(self):
744         matcher = StartsWith("bar")
745         mismatch = matcher.match("foo")
746         self.assertEqual("bar", mismatch.expected)
747
748
749 class DoesNotEndWithTests(TestCase):
750
751     run_tests_with = FullStackRunTest
752
753     def test_describe(self):
754         mismatch = DoesNotEndWith("fo", "bo")
755         self.assertEqual("'fo' does not end with 'bo'.", mismatch.describe())
756
757     def test_describe_non_ascii_unicode(self):
758         string = _u("A\xA7")
759         suffix = _u("B\xA7")
760         mismatch = DoesNotEndWith(string, suffix)
761         self.assertEqual("%s does not end with %s." % (
762             text_repr(string), text_repr(suffix)),
763             mismatch.describe())
764
765     def test_describe_non_ascii_bytes(self):
766         string = _b("A\xA7")
767         suffix = _b("B\xA7")
768         mismatch = DoesNotEndWith(string, suffix)
769         self.assertEqual("%r does not end with %r." % (string, suffix),
770             mismatch.describe())
771
772
773 class EndsWithTests(TestCase):
774
775     run_tests_with = FullStackRunTest
776
777     def test_str(self):
778         matcher = EndsWith("bar")
779         self.assertEqual("EndsWith('bar')", str(matcher))
780
781     def test_str_with_bytes(self):
782         b = _b("\xA7")
783         matcher = EndsWith(b)
784         self.assertEqual("EndsWith(%r)" % (b,), str(matcher))
785
786     def test_str_with_unicode(self):
787         u = _u("\xA7")
788         matcher = EndsWith(u)
789         self.assertEqual("EndsWith(%r)" % (u,), str(matcher))
790
791     def test_match(self):
792         matcher = EndsWith("arf")
793         self.assertIs(None, matcher.match("barf"))
794
795     def test_mismatch_returns_does_not_end_with(self):
796         matcher = EndsWith("bar")
797         self.assertIsInstance(matcher.match("foo"), DoesNotEndWith)
798
799     def test_mismatch_sets_matchee(self):
800         matcher = EndsWith("bar")
801         mismatch = matcher.match("foo")
802         self.assertEqual("foo", mismatch.matchee)
803
804     def test_mismatch_sets_expected(self):
805         matcher = EndsWith("bar")
806         mismatch = matcher.match("foo")
807         self.assertEqual("bar", mismatch.expected)
808
809
810 def run_doctest(obj, name):
811     p = doctest.DocTestParser()
812     t = p.get_doctest(
813         obj.__doc__, sys.modules[obj.__module__].__dict__, name, '', 0)
814     r = doctest.DocTestRunner()
815     output = StringIO()
816     r.run(t, out=output.write)
817     return r.failures, output.getvalue()
818
819
820 class TestMatchesListwise(TestCase):
821
822     run_tests_with = FullStackRunTest
823
824     def test_docstring(self):
825         failure_count, output = run_doctest(
826             MatchesListwise, "MatchesListwise")
827         if failure_count:
828             self.fail("Doctest failed with %s" % output)
829
830
831 class TestMatchesStructure(TestCase, TestMatchersInterface):
832
833     class SimpleClass:
834         def __init__(self, x, y):
835             self.x = x
836             self.y = y
837
838     matches_matcher = MatchesStructure(x=Equals(1), y=Equals(2))
839     matches_matches = [SimpleClass(1, 2)]
840     matches_mismatches = [
841         SimpleClass(2, 2),
842         SimpleClass(1, 1),
843         SimpleClass(3, 3),
844         ]
845
846     str_examples = [
847         ("MatchesStructure(x=Equals(1))", MatchesStructure(x=Equals(1))),
848         ("MatchesStructure(y=Equals(2))", MatchesStructure(y=Equals(2))),
849         ("MatchesStructure(x=Equals(1), y=Equals(2))",
850          MatchesStructure(x=Equals(1), y=Equals(2))),
851         ]
852
853     describe_examples = [
854         ("""\
855 Differences: [
856 3 != 1: x
857 ]""", SimpleClass(1, 2), MatchesStructure(x=Equals(3), y=Equals(2))),
858         ("""\
859 Differences: [
860 3 != 2: y
861 ]""", SimpleClass(1, 2), MatchesStructure(x=Equals(1), y=Equals(3))),
862         ("""\
863 Differences: [
864 0 != 1: x
865 0 != 2: y
866 ]""", SimpleClass(1, 2), MatchesStructure(x=Equals(0), y=Equals(0))),
867         ]
868
869     def test_fromExample(self):
870         self.assertThat(
871             self.SimpleClass(1, 2),
872             MatchesStructure.fromExample(self.SimpleClass(1, 3), 'x'))
873
874     def test_byEquality(self):
875         self.assertThat(
876             self.SimpleClass(1, 2),
877             MatchesStructure.byEquality(x=1))
878
879     def test_withStructure(self):
880         self.assertThat(
881             self.SimpleClass(1, 2),
882             MatchesStructure.byMatcher(LessThan, x=2))
883
884     def test_update(self):
885         self.assertThat(
886             self.SimpleClass(1, 2),
887             MatchesStructure(x=NotEquals(1)).update(x=Equals(1)))
888
889     def test_update_none(self):
890         self.assertThat(
891             self.SimpleClass(1, 2),
892             MatchesStructure(x=Equals(1), z=NotEquals(42)).update(
893                 z=None))
894
895
896 class TestMatchesRegex(TestCase, TestMatchersInterface):
897
898     matches_matcher = MatchesRegex('a|b')
899     matches_matches = ['a', 'b']
900     matches_mismatches = ['c']
901
902     str_examples = [
903         ("MatchesRegex('a|b')", MatchesRegex('a|b')),
904         ("MatchesRegex('a|b', re.M)", MatchesRegex('a|b', re.M)),
905         ("MatchesRegex('a|b', re.I|re.M)", MatchesRegex('a|b', re.I|re.M)),
906         ("MatchesRegex(%r)" % (_b("\xA7"),), MatchesRegex(_b("\xA7"))),
907         ("MatchesRegex(%r)" % (_u("\xA7"),), MatchesRegex(_u("\xA7"))),
908         ]
909
910     describe_examples = [
911         ("'c' does not match /a|b/", 'c', MatchesRegex('a|b')),
912         ("'c' does not match /a\d/", 'c', MatchesRegex(r'a\d')),
913         ("%r does not match /\\s+\\xa7/" % (_b('c'),),
914             _b('c'), MatchesRegex(_b("\\s+\xA7"))),
915         ("%r does not match /\\s+\\xa7/" % (_u('c'),),
916             _u('c'), MatchesRegex(_u("\\s+\xA7"))),
917         ]
918
919
920 class TestMatchesSetwise(TestCase):
921
922     run_tests_with = FullStackRunTest
923
924     def assertMismatchWithDescriptionMatching(self, value, matcher,
925                                               description_matcher):
926         mismatch = matcher.match(value)
927         if mismatch is None:
928             self.fail("%s matched %s" % (matcher, value))
929         actual_description = mismatch.describe()
930         self.assertThat(
931             actual_description,
932             Annotate(
933                 "%s matching %s" % (matcher, value),
934                 description_matcher))
935
936     def test_matches(self):
937         self.assertIs(
938             None, MatchesSetwise(Equals(1), Equals(2)).match([2, 1]))
939
940     def test_mismatches(self):
941         self.assertMismatchWithDescriptionMatching(
942             [2, 3], MatchesSetwise(Equals(1), Equals(2)),
943             MatchesRegex('.*There was 1 mismatch$', re.S))
944
945     def test_too_many_matchers(self):
946         self.assertMismatchWithDescriptionMatching(
947             [2, 3], MatchesSetwise(Equals(1), Equals(2), Equals(3)),
948             Equals('There was 1 matcher left over: Equals(1)'))
949
950     def test_too_many_values(self):
951         self.assertMismatchWithDescriptionMatching(
952             [1, 2, 3], MatchesSetwise(Equals(1), Equals(2)),
953             Equals('There was 1 value left over: [3]'))
954
955     def test_two_too_many_matchers(self):
956         self.assertMismatchWithDescriptionMatching(
957             [3], MatchesSetwise(Equals(1), Equals(2), Equals(3)),
958             MatchesRegex(
959                 'There were 2 matchers left over: Equals\([12]\), '
960                 'Equals\([12]\)'))
961
962     def test_two_too_many_values(self):
963         self.assertMismatchWithDescriptionMatching(
964             [1, 2, 3, 4], MatchesSetwise(Equals(1), Equals(2)),
965             MatchesRegex(
966                 'There were 2 values left over: \[[34], [34]\]'))
967
968     def test_mismatch_and_too_many_matchers(self):
969         self.assertMismatchWithDescriptionMatching(
970             [2, 3], MatchesSetwise(Equals(0), Equals(1), Equals(2)),
971             MatchesRegex(
972                 '.*There was 1 mismatch and 1 extra matcher: Equals\([01]\)',
973                 re.S))
974
975     def test_mismatch_and_too_many_values(self):
976         self.assertMismatchWithDescriptionMatching(
977             [2, 3, 4], MatchesSetwise(Equals(1), Equals(2)),
978             MatchesRegex(
979                 '.*There was 1 mismatch and 1 extra value: \[[34]\]',
980                 re.S))
981
982     def test_mismatch_and_two_too_many_matchers(self):
983         self.assertMismatchWithDescriptionMatching(
984             [3, 4], MatchesSetwise(
985                 Equals(0), Equals(1), Equals(2), Equals(3)),
986             MatchesRegex(
987                 '.*There was 1 mismatch and 2 extra matchers: '
988                 'Equals\([012]\), Equals\([012]\)', re.S))
989
990     def test_mismatch_and_two_too_many_values(self):
991         self.assertMismatchWithDescriptionMatching(
992             [2, 3, 4, 5], MatchesSetwise(Equals(1), Equals(2)),
993             MatchesRegex(
994                 '.*There was 1 mismatch and 2 extra values: \[[145], [145]\]',
995                 re.S))
996
997
998 class TestAfterPreprocessing(TestCase, TestMatchersInterface):
999
1000     def parity(x):
1001         return x % 2
1002
1003     matches_matcher = AfterPreprocessing(parity, Equals(1))
1004     matches_matches = [3, 5]
1005     matches_mismatches = [2]
1006
1007     str_examples = [
1008         ("AfterPreprocessing(<function parity>, Equals(1))",
1009          AfterPreprocessing(parity, Equals(1))),
1010         ]
1011
1012     describe_examples = [
1013         ("1 != 0: after <function parity> on 2", 2,
1014          AfterPreprocessing(parity, Equals(1))),
1015         ("1 != 0", 2,
1016          AfterPreprocessing(parity, Equals(1), annotate=False)),
1017         ]
1018
1019
1020 class TestMismatchDecorator(TestCase):
1021
1022     run_tests_with = FullStackRunTest
1023
1024     def test_forwards_description(self):
1025         x = Mismatch("description", {'foo': 'bar'})
1026         decorated = MismatchDecorator(x)
1027         self.assertEqual(x.describe(), decorated.describe())
1028
1029     def test_forwards_details(self):
1030         x = Mismatch("description", {'foo': 'bar'})
1031         decorated = MismatchDecorator(x)
1032         self.assertEqual(x.get_details(), decorated.get_details())
1033
1034     def test_repr(self):
1035         x = Mismatch("description", {'foo': 'bar'})
1036         decorated = MismatchDecorator(x)
1037         self.assertEqual(
1038             '<testtools.matchers.MismatchDecorator(%r)>' % (x,),
1039             repr(decorated))
1040
1041
1042 class TestAllMatch(TestCase, TestMatchersInterface):
1043
1044     matches_matcher = AllMatch(LessThan(10))
1045     matches_matches = [
1046         [9, 9, 9],
1047         (9, 9),
1048         iter([9, 9, 9, 9, 9]),
1049         ]
1050     matches_mismatches = [
1051         [11, 9, 9],
1052         iter([9, 12, 9, 11]),
1053         ]
1054
1055     str_examples = [
1056         ("AllMatch(LessThan(12))", AllMatch(LessThan(12))),
1057         ]
1058
1059     describe_examples = [
1060         ('Differences: [\n'
1061          '10 is not > 11\n'
1062          '10 is not > 10\n'
1063          ']',
1064          [11, 9, 10],
1065          AllMatch(LessThan(10))),
1066         ]
1067
1068
1069 def test_suite():
1070     from unittest import TestLoader
1071     return TestLoader().loadTestsFromName(__name__)