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
=== modified file 'NEWS'
--- NEWS 2010-10-14 22:58:49 +0000
+++ NEWS 2010-10-17 10:15:58 +0000
@@ -19,6 +19,9 @@
19* Less exception object cycles are generated (reduces peak memory use between19* Less exception object cycles are generated (reduces peak memory use between
20 garbage collection). (Martin [gz])20 garbage collection). (Martin [gz])
2121
22* New matchers 'DoesNotStartWith' and 'StartsWith' contributed by Canonical
23 from the Launchpad project. Written by James Westby.
24
22* Timestamps as produced by subunit protocol clients are now forwarded in the25* Timestamps as produced by subunit protocol clients are now forwarded in the
23 ThreadsafeForwardingResult so correct test durations can be reported.26 ThreadsafeForwardingResult so correct test durations can be reported.
24 (Martin [gz], Robert Collins, #625594)27 (Martin [gz], Robert Collins, #625594)
2528
=== modified file 'testtools/matchers.py'
--- testtools/matchers.py 2010-09-12 00:36:10 +0000
+++ testtools/matchers.py 2010-10-17 10:15:58 +0000
@@ -14,6 +14,7 @@
14__all__ = [14__all__ = [
15 'Annotate',15 'Annotate',
16 'DocTestMatches',16 'DocTestMatches',
17 'DoesNotStartWith',
17 'Equals',18 'Equals',
18 'Is',19 'Is',
19 'LessThan',20 'LessThan',
@@ -21,6 +22,7 @@
21 'MatchesAny',22 'MatchesAny',
22 'NotEquals',23 'NotEquals',
23 'Not',24 'Not',
25 'StartsWith',
24 ]26 ]
2527
26import doctest28import doctest
@@ -152,6 +154,23 @@
152 return self.matcher._describe_difference(self.with_nl)154 return self.matcher._describe_difference(self.with_nl)
153155
154156
157class DoesNotStartWith(Mismatch):
158
159 def __init__(self, matchee, expected):
160 """Create a DoesNotStartWith Mismatch.
161
162 :param matchee: the string that did not match.
163 :param expected: the string that `matchee` was expected to start
164 with.
165 """
166 self.matchee = matchee
167 self.expected = expected
168
169 def describe(self):
170 return "'%s' does not start with '%s'." % (
171 self.matchee, self.expected)
172
173
155class _BinaryComparison(object):174class _BinaryComparison(object):
156 """Matcher that compares an object to another object."""175 """Matcher that compares an object to another object."""
157176
@@ -305,6 +324,25 @@
305 return "%r matches %s" % (self.other, self.matcher)324 return "%r matches %s" % (self.other, self.matcher)
306325
307326
327class StartsWith(Matcher):
328 """Checks whether one string starts with another."""
329
330 def __init__(self, expected):
331 """Create a StartsWith Matcher.
332
333 :param expected: the string that matchees should start with.
334 """
335 self.expected = expected
336
337 def __str__(self):
338 return "Starts with '%s'." % self.expected
339
340 def match(self, matchee):
341 if not matchee.startswith(self.expected):
342 return DoesNotStartWith(matchee, self.expected)
343 return None
344
345
308class Annotate(object):346class Annotate(object):
309 """Annotates a matcher with a descriptive string.347 """Annotates a matcher with a descriptive string.
310348
311349
=== 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:58 +0000
@@ -12,6 +12,7 @@
12 Annotate,12 Annotate,
13 Equals,13 Equals,
14 DocTestMatches,14 DocTestMatches,
15 DoesNotStartWith,
15 Is,16 Is,
16 LessThan,17 LessThan,
17 MatchesAny,18 MatchesAny,
@@ -19,6 +20,7 @@
19 Mismatch,20 Mismatch,
20 Not,21 Not,
21 NotEquals,22 NotEquals,
23 StartsWith,
22 )24 )
2325
24# Silence pyflakes.26# Silence pyflakes.
@@ -221,6 +223,38 @@
221 describe_examples = [("1 != 2: foo", 2, Annotate('foo', Equals(1)))]223 describe_examples = [("1 != 2: foo", 2, Annotate('foo', Equals(1)))]
222224
223225
226class DoesNotStartWithTests(TestCase):
227
228 def test_describe(self):
229 mismatch = DoesNotStartWith("fo", "bo")
230 self.assertEqual("'fo' does not start with 'bo'.", mismatch.describe())
231
232
233class StartsWithTests(TestCase):
234
235 def test_str(self):
236 matcher = StartsWith("bar")
237 self.assertEqual("Starts with 'bar'.", str(matcher))
238
239 def test_match(self):
240 matcher = StartsWith("bar")
241 self.assertIs(None, matcher.match("barf"))
242
243 def test_mismatch_returns_does_not_start_with(self):
244 matcher = StartsWith("bar")
245 self.assertIsInstance(matcher.match("foo"), DoesNotStartWith)
246
247 def test_mismatch_sets_matchee(self):
248 matcher = StartsWith("bar")
249 mismatch = matcher.match("foo")
250 self.assertEqual("foo", mismatch.matchee)
251
252 def test_mismatch_sets_expected(self):
253 matcher = StartsWith("bar")
254 mismatch = matcher.match("foo")
255 self.assertEqual("bar", mismatch.expected)
256
257
224def test_suite():258def test_suite():
225 from unittest import TestLoader259 from unittest import TestLoader
226 return TestLoader().loadTestsFromName(__name__)260 return TestLoader().loadTestsFromName(__name__)

Subscribers

People subscribed via source and target branches