testtools-dev team mailing list archive
-
testtools-dev team
-
Mailing list archive
-
Message #00138
[Merge] lp:~lifeless/testtools/matchers into lp:testtools
Robert Collins has proposed merging lp:~lifeless/testtools/matchers into lp:testtools.
Requested reviews:
testtools developers (testtools-dev)
StartsWith and DoesNotStartWith from LP.
--
https://code.launchpad.net/~lifeless/testtools/matchers/+merge/38645
Your team testtools developers is requested to review the proposed merge of lp:~lifeless/testtools/matchers into lp:testtools.
=== modified file 'NEWS'
--- NEWS 2010-10-14 22:58:49 +0000
+++ NEWS 2010-10-17 10:15:57 +0000
@@ -19,6 +19,9 @@
* Less exception object cycles are generated (reduces peak memory use between
garbage collection). (Martin [gz])
+* New matchers 'DoesNotStartWith' and 'StartsWith' contributed by Canonical
+ from the Launchpad project. Written by James Westby.
+
* Timestamps as produced by subunit protocol clients are now forwarded in the
ThreadsafeForwardingResult so correct test durations can be reported.
(Martin [gz], Robert Collins, #625594)
=== modified file 'testtools/matchers.py'
--- testtools/matchers.py 2010-09-12 00:36:10 +0000
+++ testtools/matchers.py 2010-10-17 10:15:57 +0000
@@ -14,6 +14,7 @@
__all__ = [
'Annotate',
'DocTestMatches',
+ 'DoesNotStartWith',
'Equals',
'Is',
'LessThan',
@@ -21,6 +22,7 @@
'MatchesAny',
'NotEquals',
'Not',
+ 'StartsWith',
]
import doctest
@@ -152,6 +154,23 @@
return self.matcher._describe_difference(self.with_nl)
+class DoesNotStartWith(Mismatch):
+
+ def __init__(self, matchee, expected):
+ """Create a DoesNotStartWith Mismatch.
+
+ :param matchee: the string that did not match.
+ :param expected: the string that `matchee` was expected to start
+ with.
+ """
+ self.matchee = matchee
+ self.expected = expected
+
+ def describe(self):
+ return "'%s' does not start with '%s'." % (
+ self.matchee, self.expected)
+
+
class _BinaryComparison(object):
"""Matcher that compares an object to another object."""
@@ -305,6 +324,25 @@
return "%r matches %s" % (self.other, self.matcher)
+class StartsWith(Matcher):
+ """Checks whether one string starts with another."""
+
+ def __init__(self, expected):
+ """Create a StartsWith Matcher.
+
+ :param expected: the string that matchees should start with.
+ """
+ self.expected = expected
+
+ def __str__(self):
+ return "Starts with '%s'." % self.expected
+
+ def match(self, matchee):
+ if not matchee.startswith(self.expected):
+ return DoesNotStartWith(matchee, self.expected)
+ return None
+
+
class Annotate(object):
"""Annotates a matcher with a descriptive string.
=== modified file 'testtools/tests/test_matchers.py'
--- testtools/tests/test_matchers.py 2010-08-17 13:08:01 +0000
+++ testtools/tests/test_matchers.py 2010-10-17 10:15:57 +0000
@@ -12,6 +12,7 @@
Annotate,
Equals,
DocTestMatches,
+ DoesNotStartWith,
Is,
LessThan,
MatchesAny,
@@ -19,6 +20,7 @@
Mismatch,
Not,
NotEquals,
+ StartsWith,
)
# Silence pyflakes.
@@ -221,6 +223,38 @@
describe_examples = [("1 != 2: foo", 2, Annotate('foo', Equals(1)))]
+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)
+
+
def test_suite():
from unittest import TestLoader
return TestLoader().loadTestsFromName(__name__)
Follow ups