← Back to team overview

testtools-dev team mailing list archive

[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