Merge lp:~jml/testtools/any-match into lp:~testtools-committers/testtools/trunk

Proposed by Jonathan Lange
Status: Merged
Merged at revision: 294
Proposed branch: lp:~jml/testtools/any-match
Merge into: lp:~testtools-committers/testtools/trunk
Diff against target: 99 lines (+60/-0)
3 files modified
NEWS (+7/-0)
testtools/matchers/_higherorder.py (+20/-0)
testtools/tests/matchers/test_higherorder.py (+33/-0)
To merge this branch: bzr merge lp:~jml/testtools/any-match
Reviewer Review Type Date Requested Status
Jelmer Vernooij Approve
Review via email: mp+139720@code.launchpad.net

Commit message

Add new matcher, AnyMatch

Description of the change

Deep in the yak stack I go.

This adds a new matcher, AnyMatch. It's a lot like AllMatch, but where AllMatch
guarantees that all items in a collection match a given matcher, this checks that
just one of them do.

Contains(x) is equivalent to AnyMatch(Equals(x)).

Feels a lot like we're dancing around a deeper issue in Python.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

Looks good. The name is somewhat confusing considering we also have MatchesAny, but it is consistent with the already existing AllMatch (and MatchesAll).

I agree there's a deeper issue here, but until we put a finger on what it is exactly and what the alternatives are this seems reasonable.

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 2012-12-10 23:48:16 +0000
3+++ NEWS 2012-12-13 15:10:43 +0000
4@@ -6,6 +6,13 @@
5 NEXT
6 ~~~~
7
8+Improvements
9+------------
10+
11+* ``AnyMatch`` added, a new matcher that matches when any item in a collection
12+ matches the given matcher. (Jonathan Lange)
13+
14+
15 0.9.22
16 ~~~~~~
17
18
19=== modified file 'testtools/matchers/_higherorder.py'
20--- testtools/matchers/_higherorder.py 2012-09-10 11:37:46 +0000
21+++ testtools/matchers/_higherorder.py 2012-12-13 15:10:43 +0000
22@@ -236,6 +236,26 @@
23 return MismatchesAll(mismatches)
24
25
26+class AnyMatch(object):
27+ """Matches if any of the provided values match the given matcher."""
28+
29+ def __init__(self, matcher):
30+ self.matcher = matcher
31+
32+ def __str__(self):
33+ return 'AnyMatch(%s)' % (self.matcher,)
34+
35+ def match(self, values):
36+ mismatches = []
37+ for value in values:
38+ mismatch = self.matcher.match(value)
39+ if mismatch:
40+ mismatches.append(mismatch)
41+ else:
42+ return None
43+ return MismatchesAll(mismatches)
44+
45+
46 class MatchesPredicate(Matcher):
47 """Match if a given function returns True.
48
49
50=== modified file 'testtools/tests/matchers/test_higherorder.py'
51--- testtools/tests/matchers/test_higherorder.py 2012-09-08 17:21:06 +0000
52+++ testtools/tests/matchers/test_higherorder.py 2012-12-13 15:10:43 +0000
53@@ -14,6 +14,7 @@
54 AllMatch,
55 Annotate,
56 AnnotatedMismatch,
57+ AnyMatch,
58 MatchesAny,
59 MatchesAll,
60 MatchesPredicate,
61@@ -50,6 +51,38 @@
62 ]
63
64
65+class TestAnyMatch(TestCase, TestMatchersInterface):
66+
67+ matches_matcher = AnyMatch(Equals('elephant'))
68+ matches_matches = [
69+ ['grass', 'cow', 'steak', 'milk', 'elephant'],
70+ (13, 'elephant'),
71+ ['elephant', 'elephant', 'elephant'],
72+ set(['hippo', 'rhino', 'elephant']),
73+ ]
74+ matches_mismatches = [
75+ [],
76+ ['grass', 'cow', 'steak', 'milk'],
77+ (13, 12, 10),
78+ ['element', 'hephalump', 'pachyderm'],
79+ set(['hippo', 'rhino', 'diplodocus']),
80+ ]
81+
82+ str_examples = [
83+ ("AnyMatch(Equals('elephant'))", AnyMatch(Equals('elephant'))),
84+ ]
85+
86+ describe_examples = [
87+ ('Differences: [\n'
88+ '7 != 11\n'
89+ '7 != 9\n'
90+ '7 != 10\n'
91+ ']',
92+ [11, 9, 10],
93+ AnyMatch(Equals(7))),
94+ ]
95+
96+
97 class TestAfterPreprocessing(TestCase, TestMatchersInterface):
98
99 def parity(x):

Subscribers

People subscribed via source and target branches