summaryrefslogtreecommitdiff
path: root/lib/testtools/testtools/tests/test_matchers.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/testtools/testtools/tests/test_matchers.py')
-rw-r--r--lib/testtools/testtools/tests/test_matchers.py228
1 files changed, 226 insertions, 2 deletions
diff --git a/lib/testtools/testtools/tests/test_matchers.py b/lib/testtools/testtools/tests/test_matchers.py
index 164a6a0c50..9cc2c010ef 100644
--- a/lib/testtools/testtools/tests/test_matchers.py
+++ b/lib/testtools/testtools/tests/test_matchers.py
@@ -1,8 +1,9 @@
-# Copyright (c) 2008 Jonathan M. Lange. See LICENSE for details.
+# Copyright (c) 2008-2010 Jonathan M. Lange. See LICENSE for details.
"""Tests for matchers."""
import doctest
+import sys
from testtools import (
Matcher, # check that Matcher is exposed at the top level for docs.
@@ -12,13 +13,21 @@ from testtools.matchers import (
Annotate,
Equals,
DocTestMatches,
+ DoesNotEndWith,
+ DoesNotStartWith,
+ EndsWith,
+ KeysEqual,
Is,
LessThan,
MatchesAny,
MatchesAll,
+ MatchesException,
Mismatch,
Not,
NotEquals,
+ Raises,
+ raises,
+ StartsWith,
)
# Silence pyflakes.
@@ -34,7 +43,8 @@ class TestMismatch(TestCase):
def test_constructor_no_arguments(self):
mismatch = Mismatch()
- self.assertRaises(NotImplementedError, mismatch.describe)
+ self.assertThat(mismatch.describe,
+ Raises(MatchesException(NotImplementedError)))
self.assertEqual({}, mismatch.get_details())
@@ -152,6 +162,58 @@ class TestLessThanInterface(TestCase, TestMatchersInterface):
describe_examples = [('4 is >= 4', 4, LessThan(4))]
+def make_error(type, *args, **kwargs):
+ try:
+ raise type(*args, **kwargs)
+ except type:
+ return sys.exc_info()
+
+
+class TestMatchesExceptionInstanceInterface(TestCase, TestMatchersInterface):
+
+ matches_matcher = MatchesException(ValueError("foo"))
+ error_foo = make_error(ValueError, 'foo')
+ error_bar = make_error(ValueError, 'bar')
+ error_base_foo = make_error(Exception, 'foo')
+ matches_matches = [error_foo]
+ matches_mismatches = [error_bar, error_base_foo]
+
+ str_examples = [
+ ("MatchesException(Exception('foo',))",
+ MatchesException(Exception('foo')))
+ ]
+ describe_examples = [
+ ("<type 'exceptions.Exception'> is not a "
+ "<type 'exceptions.ValueError'>",
+ error_base_foo,
+ MatchesException(ValueError("foo"))),
+ ("ValueError('bar',) has different arguments to ValueError('foo',).",
+ error_bar,
+ MatchesException(ValueError("foo"))),
+ ]
+
+
+class TestMatchesExceptionTypeInterface(TestCase, TestMatchersInterface):
+
+ matches_matcher = MatchesException(ValueError)
+ error_foo = make_error(ValueError, 'foo')
+ error_sub = make_error(UnicodeError, 'bar')
+ error_base_foo = make_error(Exception, 'foo')
+ matches_matches = [error_foo, error_sub]
+ matches_mismatches = [error_base_foo]
+
+ str_examples = [
+ ("MatchesException(<type 'exceptions.Exception'>)",
+ MatchesException(Exception))
+ ]
+ describe_examples = [
+ ("<type 'exceptions.Exception'> is not a "
+ "<type 'exceptions.ValueError'>",
+ error_base_foo,
+ MatchesException(ValueError)),
+ ]
+
+
class TestNotInterface(TestCase, TestMatchersInterface):
matches_matcher = Not(Equals(1))
@@ -209,6 +271,31 @@ class TestMatchesAllInterface(TestCase, TestMatchersInterface):
1, MatchesAll(NotEquals(1), NotEquals(2)))]
+class TestKeysEqual(TestCase, TestMatchersInterface):
+
+ matches_matcher = KeysEqual('foo', 'bar')
+ matches_matches = [
+ {'foo': 0, 'bar': 1},
+ ]
+ matches_mismatches = [
+ {},
+ {'foo': 0},
+ {'bar': 1},
+ {'foo': 0, 'bar': 1, 'baz': 2},
+ {'a': None, 'b': None, 'c': None},
+ ]
+
+ str_examples = [
+ ("KeysEqual('foo', 'bar')", KeysEqual('foo', 'bar')),
+ ]
+
+ describe_examples = [
+ ("['bar', 'foo'] does not match {'baz': 2, 'foo': 0, 'bar': 1}: "
+ "Keys not equal",
+ {'foo': 0, 'bar': 1, 'baz': 2}, KeysEqual('foo', 'bar')),
+ ]
+
+
class TestAnnotate(TestCase, TestMatchersInterface):
matches_matcher = Annotate("foo", Equals(1))
@@ -221,6 +308,143 @@ class TestAnnotate(TestCase, TestMatchersInterface):
describe_examples = [("1 != 2: foo", 2, Annotate('foo', Equals(1)))]
+class TestRaisesInterface(TestCase, TestMatchersInterface):
+
+ matches_matcher = Raises()
+ def boom():
+ raise Exception('foo')
+ matches_matches = [boom]
+ matches_mismatches = [lambda:None]
+
+ # Tricky to get function objects to render constantly, and the interfaces
+ # helper uses assertEqual rather than (for instance) DocTestMatches.
+ str_examples = []
+
+ describe_examples = []
+
+
+class TestRaisesExceptionMatcherInterface(TestCase, TestMatchersInterface):
+
+ matches_matcher = Raises(
+ exception_matcher=MatchesException(Exception('foo')))
+ def boom_bar():
+ raise Exception('bar')
+ def boom_foo():
+ raise Exception('foo')
+ matches_matches = [boom_foo]
+ matches_mismatches = [lambda:None, boom_bar]
+
+ # Tricky to get function objects to render constantly, and the interfaces
+ # helper uses assertEqual rather than (for instance) DocTestMatches.
+ str_examples = []
+
+ describe_examples = []
+
+
+class TestRaisesBaseTypes(TestCase):
+
+ def raiser(self):
+ raise KeyboardInterrupt('foo')
+
+ def test_KeyboardInterrupt_matched(self):
+ # When KeyboardInterrupt is matched, it is swallowed.
+ matcher = Raises(MatchesException(KeyboardInterrupt))
+ self.assertThat(self.raiser, matcher)
+
+ def test_KeyboardInterrupt_propogates(self):
+ # The default 'it raised' propogates KeyboardInterrupt.
+ match_keyb = Raises(MatchesException(KeyboardInterrupt))
+ def raise_keyb_from_match():
+ matcher = Raises()
+ matcher.match(self.raiser)
+ self.assertThat(raise_keyb_from_match, match_keyb)
+
+ def test_KeyboardInterrupt_match_Exception_propogates(self):
+ # If the raised exception isn't matched, and it is not a subclass of
+ # Exception, it is propogated.
+ match_keyb = Raises(MatchesException(KeyboardInterrupt))
+ def raise_keyb_from_match():
+ matcher = Raises(MatchesException(Exception))
+ matcher.match(self.raiser)
+ self.assertThat(raise_keyb_from_match, match_keyb)
+
+
+class TestRaisesConvenience(TestCase):
+
+ def test_exc_type(self):
+ self.assertThat(lambda: 1/0, raises(ZeroDivisionError))
+
+ def test_exc_value(self):
+ e = RuntimeError("You lose!")
+ def raiser():
+ raise e
+ self.assertThat(raiser, raises(e))
+
+
+class DoesNotStartWithTests(TestCase):
+
+ def test_describe(self):
+ mismatch = DoesNotStartWith("fo", "bo")
+ self.assertEqual("'fo' does not start with 'bo'.", mismatch.describe())
+
+
+class StartsWithTests(TestCase):
+
+ def test_str(self):
+ matcher = StartsWith("bar")
+ self.assertEqual("Starts with 'bar'.", str(matcher))
+
+ def test_match(self):
+ matcher = StartsWith("bar")
+ self.assertIs(None, matcher.match("barf"))
+
+ def test_mismatch_returns_does_not_start_with(self):
+ matcher = StartsWith("bar")
+ self.assertIsInstance(matcher.match("foo"), DoesNotStartWith)
+
+ def test_mismatch_sets_matchee(self):
+ matcher = StartsWith("bar")
+ mismatch = matcher.match("foo")
+ self.assertEqual("foo", mismatch.matchee)
+
+ def test_mismatch_sets_expected(self):
+ matcher = StartsWith("bar")
+ mismatch = matcher.match("foo")
+ self.assertEqual("bar", mismatch.expected)
+
+
+class DoesNotEndWithTests(TestCase):
+
+ def test_describe(self):
+ mismatch = DoesNotEndWith("fo", "bo")
+ self.assertEqual("'fo' does not end with 'bo'.", mismatch.describe())
+
+
+class EndsWithTests(TestCase):
+
+ def test_str(self):
+ matcher = EndsWith("bar")
+ self.assertEqual("Ends with 'bar'.", str(matcher))
+
+ def test_match(self):
+ matcher = EndsWith("arf")
+ self.assertIs(None, matcher.match("barf"))
+
+ def test_mismatch_returns_does_not_end_with(self):
+ matcher = EndsWith("bar")
+ self.assertIsInstance(matcher.match("foo"), DoesNotEndWith)
+
+ def test_mismatch_sets_matchee(self):
+ matcher = EndsWith("bar")
+ mismatch = matcher.match("foo")
+ self.assertEqual("foo", mismatch.matchee)
+
+ def test_mismatch_sets_expected(self):
+ matcher = EndsWith("bar")
+ mismatch = matcher.match("foo")
+ self.assertEqual("bar", mismatch.expected)
+
+
def test_suite():
from unittest import TestLoader
return TestLoader().loadTestsFromName(__name__)