~bzr/ubuntu/natty/python-testtools/bzr-ppa

« back to all changes in this revision

Viewing changes to testtools/tests/test_matchers.py

  • Committer: Robert Collins
  • Date: 2010-11-14 15:49:58 UTC
  • mfrom: (16.11.4 upstream)
  • Revision ID: robertc@robertcollins.net-20101114154958-lwb16rdhehq6q020
New snapshot for testing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (c) 2008 Jonathan M. Lange. See LICENSE for details.
 
1
# Copyright (c) 2008-2010 Jonathan M. Lange. See LICENSE for details.
2
2
 
3
3
"""Tests for matchers."""
4
4
 
5
5
import doctest
 
6
import sys
6
7
 
7
8
from testtools import (
8
9
    Matcher, # check that Matcher is exposed at the top level for docs.
12
13
    Annotate,
13
14
    Equals,
14
15
    DocTestMatches,
 
16
    DoesNotStartWith,
 
17
    KeysEqual,
 
18
    Is,
 
19
    LessThan,
15
20
    MatchesAny,
16
21
    MatchesAll,
 
22
    MatchesException,
 
23
    Mismatch,
17
24
    Not,
18
25
    NotEquals,
 
26
    Raises,
 
27
    raises,
 
28
    StartsWith,
19
29
    )
20
30
 
21
 
 
22
 
class TestMatchersInterface:
 
31
# Silence pyflakes.
 
32
Matcher
 
33
 
 
34
 
 
35
class TestMismatch(TestCase):
 
36
 
 
37
    def test_constructor_arguments(self):
 
38
        mismatch = Mismatch("some description", {'detail': "things"})
 
39
        self.assertEqual("some description", mismatch.describe())
 
40
        self.assertEqual({'detail': "things"}, mismatch.get_details())
 
41
 
 
42
    def test_constructor_no_arguments(self):
 
43
        mismatch = Mismatch()
 
44
        self.assertThat(mismatch.describe,
 
45
            Raises(MatchesException(NotImplementedError)))
 
46
        self.assertEqual({}, mismatch.get_details())
 
47
 
 
48
 
 
49
class TestMatchersInterface(object):
23
50
 
24
51
    def test_matches_match(self):
25
52
        matcher = self.matches_matcher
45
72
            mismatch = matcher.match(matchee)
46
73
            self.assertEqual(difference, mismatch.describe())
47
74
 
 
75
    def test_mismatch_details(self):
 
76
        # The mismatch object must provide get_details, which must return a
 
77
        # dictionary mapping names to Content objects.
 
78
        examples = self.describe_examples
 
79
        for difference, matchee, matcher in examples:
 
80
            mismatch = matcher.match(matchee)
 
81
            details = mismatch.get_details()
 
82
            self.assertEqual(dict(details), details)
 
83
 
48
84
 
49
85
class TestDocTestMatchesInterface(TestCase, TestMatchersInterface):
50
86
 
97
133
    describe_examples = [("1 == 1", 1, NotEquals(1))]
98
134
 
99
135
 
 
136
class TestIsInterface(TestCase, TestMatchersInterface):
 
137
 
 
138
    foo = object()
 
139
    bar = object()
 
140
 
 
141
    matches_matcher = Is(foo)
 
142
    matches_matches = [foo]
 
143
    matches_mismatches = [bar, 1]
 
144
 
 
145
    str_examples = [("Is(2)", Is(2))]
 
146
 
 
147
    describe_examples = [("1 is not 2", 2, Is(1))]
 
148
 
 
149
 
 
150
class TestLessThanInterface(TestCase, TestMatchersInterface):
 
151
 
 
152
    matches_matcher = LessThan(4)
 
153
    matches_matches = [-5, 3]
 
154
    matches_mismatches = [4, 5, 5000]
 
155
 
 
156
    str_examples = [
 
157
        ("LessThan(12)", LessThan(12)),
 
158
        ]
 
159
 
 
160
    describe_examples = [('4 is >= 4', 4, LessThan(4))]
 
161
 
 
162
 
 
163
def make_error(type, *args, **kwargs):
 
164
    try:
 
165
        raise type(*args, **kwargs)
 
166
    except type:
 
167
        return sys.exc_info()
 
168
 
 
169
 
 
170
class TestMatchesExceptionInstanceInterface(TestCase, TestMatchersInterface):
 
171
 
 
172
    matches_matcher = MatchesException(ValueError("foo"))
 
173
    error_foo = make_error(ValueError, 'foo')
 
174
    error_bar = make_error(ValueError, 'bar')
 
175
    error_base_foo = make_error(Exception, 'foo')
 
176
    matches_matches = [error_foo]
 
177
    matches_mismatches = [error_bar, error_base_foo]
 
178
 
 
179
    str_examples = [
 
180
        ("MatchesException(Exception('foo',))",
 
181
         MatchesException(Exception('foo')))
 
182
        ]
 
183
    describe_examples = [
 
184
        ("<type 'exceptions.Exception'> is not a "
 
185
         "<type 'exceptions.ValueError'>",
 
186
         error_base_foo,
 
187
         MatchesException(ValueError("foo"))),
 
188
        ("ValueError('bar',) has different arguments to ValueError('foo',).",
 
189
         error_bar,
 
190
         MatchesException(ValueError("foo"))),
 
191
        ]
 
192
 
 
193
 
 
194
class TestMatchesExceptionTypeInterface(TestCase, TestMatchersInterface):
 
195
 
 
196
    matches_matcher = MatchesException(ValueError)
 
197
    error_foo = make_error(ValueError, 'foo')
 
198
    error_sub = make_error(UnicodeError, 'bar')
 
199
    error_base_foo = make_error(Exception, 'foo')
 
200
    matches_matches = [error_foo, error_sub]
 
201
    matches_mismatches = [error_base_foo]
 
202
 
 
203
    str_examples = [
 
204
        ("MatchesException(<type 'exceptions.Exception'>)",
 
205
         MatchesException(Exception))
 
206
        ]
 
207
    describe_examples = [
 
208
        ("<type 'exceptions.Exception'> is not a "
 
209
         "<type 'exceptions.ValueError'>",
 
210
         error_base_foo,
 
211
         MatchesException(ValueError)),
 
212
        ]
 
213
 
 
214
 
100
215
class TestNotInterface(TestCase, TestMatchersInterface):
101
216
 
102
217
    matches_matcher = Not(Equals(1))
154
269
                          1, MatchesAll(NotEquals(1), NotEquals(2)))]
155
270
 
156
271
 
 
272
class TestKeysEqual(TestCase, TestMatchersInterface):
 
273
 
 
274
    matches_matcher = KeysEqual('foo', 'bar')
 
275
    matches_matches = [
 
276
        {'foo': 0, 'bar': 1},
 
277
        ]
 
278
    matches_mismatches = [
 
279
        {},
 
280
        {'foo': 0},
 
281
        {'bar': 1},
 
282
        {'foo': 0, 'bar': 1, 'baz': 2},
 
283
        {'a': None, 'b': None, 'c': None},
 
284
        ]
 
285
 
 
286
    str_examples = [
 
287
        ("KeysEqual('foo', 'bar')", KeysEqual('foo', 'bar')),
 
288
        ]
 
289
 
 
290
    describe_examples = [
 
291
        ("['bar', 'foo'] does not match {'baz': 2, 'foo': 0, 'bar': 1}: "
 
292
         "Keys not equal",
 
293
         {'foo': 0, 'bar': 1, 'baz': 2}, KeysEqual('foo', 'bar')),
 
294
        ]
 
295
 
 
296
 
157
297
class TestAnnotate(TestCase, TestMatchersInterface):
158
298
 
159
299
    matches_matcher = Annotate("foo", Equals(1))
166
306
    describe_examples = [("1 != 2: foo", 2, Annotate('foo', Equals(1)))]
167
307
 
168
308
 
 
309
class TestRaisesInterface(TestCase, TestMatchersInterface):
 
310
 
 
311
    matches_matcher = Raises()
 
312
    def boom():
 
313
        raise Exception('foo')
 
314
    matches_matches = [boom]
 
315
    matches_mismatches = [lambda:None]
 
316
 
 
317
    # Tricky to get function objects to render constantly, and the interfaces
 
318
    # helper uses assertEqual rather than (for instance) DocTestMatches.
 
319
    str_examples = []
 
320
 
 
321
    describe_examples = []
 
322
 
 
323
 
 
324
class TestRaisesExceptionMatcherInterface(TestCase, TestMatchersInterface):
 
325
 
 
326
    matches_matcher = Raises(
 
327
        exception_matcher=MatchesException(Exception('foo')))
 
328
    def boom_bar():
 
329
        raise Exception('bar')
 
330
    def boom_foo():
 
331
        raise Exception('foo')
 
332
    matches_matches = [boom_foo]
 
333
    matches_mismatches = [lambda:None, boom_bar]
 
334
 
 
335
    # Tricky to get function objects to render constantly, and the interfaces
 
336
    # helper uses assertEqual rather than (for instance) DocTestMatches.
 
337
    str_examples = []
 
338
 
 
339
    describe_examples = []
 
340
 
 
341
 
 
342
class TestRaisesBaseTypes(TestCase):
 
343
 
 
344
    def raiser(self):
 
345
        raise KeyboardInterrupt('foo')
 
346
 
 
347
    def test_KeyboardInterrupt_matched(self):
 
348
        # When KeyboardInterrupt is matched, it is swallowed.
 
349
        matcher = Raises(MatchesException(KeyboardInterrupt))
 
350
        self.assertThat(self.raiser, matcher)
 
351
 
 
352
    def test_KeyboardInterrupt_propogates(self):
 
353
        # The default 'it raised' propogates KeyboardInterrupt.
 
354
        match_keyb = Raises(MatchesException(KeyboardInterrupt))
 
355
        def raise_keyb_from_match():
 
356
            matcher = Raises()
 
357
            matcher.match(self.raiser)
 
358
        self.assertThat(raise_keyb_from_match, match_keyb)
 
359
 
 
360
    def test_KeyboardInterrupt_match_Exception_propogates(self):
 
361
        # If the raised exception isn't matched, and it is not a subclass of
 
362
        # Exception, it is propogated.
 
363
        match_keyb = Raises(MatchesException(KeyboardInterrupt))
 
364
        def raise_keyb_from_match():
 
365
            matcher = Raises(MatchesException(Exception))
 
366
            matcher.match(self.raiser)
 
367
        self.assertThat(raise_keyb_from_match, match_keyb)
 
368
 
 
369
 
 
370
class TestRaisesConvenience(TestCase):
 
371
 
 
372
    def test_exc_type(self):
 
373
        self.assertThat(lambda: 1/0, raises(ZeroDivisionError))
 
374
 
 
375
    def test_exc_value(self):
 
376
        e = RuntimeError("You lose!")
 
377
        def raiser():
 
378
            raise e
 
379
        self.assertThat(raiser, raises(e))
 
380
 
 
381
 
 
382
class DoesNotStartWithTests(TestCase):
 
383
 
 
384
    def test_describe(self):
 
385
        mismatch = DoesNotStartWith("fo", "bo")
 
386
        self.assertEqual("'fo' does not start with 'bo'.", mismatch.describe())
 
387
 
 
388
 
 
389
class StartsWithTests(TestCase):
 
390
 
 
391
    def test_str(self):
 
392
        matcher = StartsWith("bar")
 
393
        self.assertEqual("Starts with 'bar'.", str(matcher))
 
394
 
 
395
    def test_match(self):
 
396
        matcher = StartsWith("bar")
 
397
        self.assertIs(None, matcher.match("barf"))
 
398
 
 
399
    def test_mismatch_returns_does_not_start_with(self):
 
400
        matcher = StartsWith("bar")
 
401
        self.assertIsInstance(matcher.match("foo"), DoesNotStartWith)
 
402
 
 
403
    def test_mismatch_sets_matchee(self):
 
404
        matcher = StartsWith("bar")
 
405
        mismatch = matcher.match("foo")
 
406
        self.assertEqual("foo", mismatch.matchee)
 
407
 
 
408
    def test_mismatch_sets_expected(self):
 
409
        matcher = StartsWith("bar")
 
410
        mismatch = matcher.match("foo")
 
411
        self.assertEqual("bar", mismatch.expected)
 
412
 
 
413
 
169
414
def test_suite():
170
415
    from unittest import TestLoader
171
416
    return TestLoader().loadTestsFromName(__name__)