Merge lp:~lifeless/testtools/matchers into lp:~testtools-committers/testtools/trunk

Proposed by Robert Collins
Status: Merged
Approved by: Jonathan Lange
Approved revision: 104
Merged at revision: 104
Proposed branch: lp:~lifeless/testtools/matchers
Merge into: lp:~testtools-committers/testtools/trunk
Diff against target: 142 lines (+75/-0)
3 files modified
NEWS (+3/-0)
testtools/matchers.py (+38/-0)
testtools/tests/test_matchers.py (+34/-0)
To merge this branch: bzr merge lp:~lifeless/testtools/matchers
Reviewer Review Type Date Requested Status
Jonathan Lange Approve
Review via email: mp+38645@code.launchpad.net

Description of the change

StartsWith and DoesNotStartWith from LP.

To post a comment you must log in.
Revision history for this message
Jonathan Lange (jml) wrote :

All good. Thanks.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2010-10-14 22:58:49 +0000
3+++ NEWS 2010-10-17 10:15:58 +0000
4@@ -19,6 +19,9 @@
5 * Less exception object cycles are generated (reduces peak memory use between
6 garbage collection). (Martin [gz])
7
8+* New matchers 'DoesNotStartWith' and 'StartsWith' contributed by Canonical
9+ from the Launchpad project. Written by James Westby.
10+
11 * Timestamps as produced by subunit protocol clients are now forwarded in the
12 ThreadsafeForwardingResult so correct test durations can be reported.
13 (Martin [gz], Robert Collins, #625594)
14
15=== modified file 'testtools/matchers.py'
16--- testtools/matchers.py 2010-09-12 00:36:10 +0000
17+++ testtools/matchers.py 2010-10-17 10:15:58 +0000
18@@ -14,6 +14,7 @@
19 __all__ = [
20 'Annotate',
21 'DocTestMatches',
22+ 'DoesNotStartWith',
23 'Equals',
24 'Is',
25 'LessThan',
26@@ -21,6 +22,7 @@
27 'MatchesAny',
28 'NotEquals',
29 'Not',
30+ 'StartsWith',
31 ]
32
33 import doctest
34@@ -152,6 +154,23 @@
35 return self.matcher._describe_difference(self.with_nl)
36
37
38+class DoesNotStartWith(Mismatch):
39+
40+ def __init__(self, matchee, expected):
41+ """Create a DoesNotStartWith Mismatch.
42+
43+ :param matchee: the string that did not match.
44+ :param expected: the string that `matchee` was expected to start
45+ with.
46+ """
47+ self.matchee = matchee
48+ self.expected = expected
49+
50+ def describe(self):
51+ return "'%s' does not start with '%s'." % (
52+ self.matchee, self.expected)
53+
54+
55 class _BinaryComparison(object):
56 """Matcher that compares an object to another object."""
57
58@@ -305,6 +324,25 @@
59 return "%r matches %s" % (self.other, self.matcher)
60
61
62+class StartsWith(Matcher):
63+ """Checks whether one string starts with another."""
64+
65+ def __init__(self, expected):
66+ """Create a StartsWith Matcher.
67+
68+ :param expected: the string that matchees should start with.
69+ """
70+ self.expected = expected
71+
72+ def __str__(self):
73+ return "Starts with '%s'." % self.expected
74+
75+ def match(self, matchee):
76+ if not matchee.startswith(self.expected):
77+ return DoesNotStartWith(matchee, self.expected)
78+ return None
79+
80+
81 class Annotate(object):
82 """Annotates a matcher with a descriptive string.
83
84
85=== modified file 'testtools/tests/test_matchers.py'
86--- testtools/tests/test_matchers.py 2010-08-17 13:08:01 +0000
87+++ testtools/tests/test_matchers.py 2010-10-17 10:15:58 +0000
88@@ -12,6 +12,7 @@
89 Annotate,
90 Equals,
91 DocTestMatches,
92+ DoesNotStartWith,
93 Is,
94 LessThan,
95 MatchesAny,
96@@ -19,6 +20,7 @@
97 Mismatch,
98 Not,
99 NotEquals,
100+ StartsWith,
101 )
102
103 # Silence pyflakes.
104@@ -221,6 +223,38 @@
105 describe_examples = [("1 != 2: foo", 2, Annotate('foo', Equals(1)))]
106
107
108+class DoesNotStartWithTests(TestCase):
109+
110+ def test_describe(self):
111+ mismatch = DoesNotStartWith("fo", "bo")
112+ self.assertEqual("'fo' does not start with 'bo'.", mismatch.describe())
113+
114+
115+class StartsWithTests(TestCase):
116+
117+ def test_str(self):
118+ matcher = StartsWith("bar")
119+ self.assertEqual("Starts with 'bar'.", str(matcher))
120+
121+ def test_match(self):
122+ matcher = StartsWith("bar")
123+ self.assertIs(None, matcher.match("barf"))
124+
125+ def test_mismatch_returns_does_not_start_with(self):
126+ matcher = StartsWith("bar")
127+ self.assertIsInstance(matcher.match("foo"), DoesNotStartWith)
128+
129+ def test_mismatch_sets_matchee(self):
130+ matcher = StartsWith("bar")
131+ mismatch = matcher.match("foo")
132+ self.assertEqual("foo", mismatch.matchee)
133+
134+ def test_mismatch_sets_expected(self):
135+ matcher = StartsWith("bar")
136+ mismatch = matcher.match("foo")
137+ self.assertEqual("bar", mismatch.expected)
138+
139+
140 def test_suite():
141 from unittest import TestLoader
142 return TestLoader().loadTestsFromName(__name__)

Subscribers

People subscribed via source and target branches