Merge lp:~jml/testtools/structure-from-dict into lp:~testtools-committers/testtools/trunk

Proposed by Jonathan Lange
Status: Merged
Merged at revision: 204
Proposed branch: lp:~jml/testtools/structure-from-dict
Merge into: lp:~testtools-committers/testtools/trunk
Diff against target: 81 lines (+31/-0)
4 files modified
NEWS (+3/-0)
doc/for-test-authors.rst (+10/-0)
testtools/matchers.py (+13/-0)
testtools/tests/test_matchers.py (+5/-0)
To merge this branch: bzr merge lp:~jml/testtools/structure-from-dict
Reviewer Review Type Date Requested Status
testtools developers Pending
Review via email: mp+68409@code.launchpad.net

Description of the change

Inspired by a post to the launchpad-dev mailing list, this adds a new factory for MatchesStructure that takes the kwargs and assumes that we want to match the values by equality.

To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote :

Two small thoughts.

Rather than byEquality, consider ByEquality - I personally find the
distinction nice for classmethods.

Secondly, perhaps there is a helper waiting to get out in there:
BuildStructure(Equals, foo=3, bar=5)
BuildStructure(LessThan, foo=4, bar='then')

otherwise looks great.

-Rob

Revision history for this message
Jonathan Lange (jml) wrote :

There are three classmethods in testtools, two are does with normal method style (make_factory, if_message) and the third is fromExample on MatchesStructure. I'd rather not introduce a third style now. Also, my preference runs to normal style naming for class methods.

Will drop in the helper.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2011-07-06 23:09:46 +0000
3+++ NEWS 2011-07-19 15:38:31 +0000
4@@ -19,6 +19,9 @@
5 * Less boilerplate displayed in test failures and errors.
6 (Jonathan Lange, #660852)
7
8+* ``MatchesStructure.byEquality`` added to make the common case of matching
9+ many attributes by equality much easier. (Jonathan Lange)
10+
11 * New convenience assertions, ``assertIsNone`` and ``assertIsNotNone``.
12 (Christian Kampka)
13
14
15=== modified file 'doc/for-test-authors.rst'
16--- doc/for-test-authors.rst 2011-06-30 17:01:10 +0000
17+++ doc/for-test-authors.rst 2011-07-19 15:38:31 +0000
18@@ -584,6 +584,16 @@
19 matcher = MatchesStructure(a=Equals(1), b=Equals(2))
20 self.assertThat(foo, matcher)
21
22+Since all of the matchers used were ``Equals``, we could also write this using
23+the ``byEquality`` helper::
24+
25+ def test_matches_structure_example(self):
26+ foo = Foo()
27+ foo.a = 1
28+ foo.b = 2
29+ matcher = MatchesStructure.byEquality(a=1, b=2)
30+ self.assertThat(foo, matcher)
31+
32 ``MatchesStructure.from_example`` takes an object and a list of attributes and
33 creates a ``MatchesStructure`` matcher where each attribute of the matched
34 object must equal each attribute of the example object. For example::
35
36=== modified file 'testtools/matchers.py'
37--- testtools/matchers.py 2011-07-18 20:29:08 +0000
38+++ testtools/matchers.py 2011-07-19 15:38:31 +0000
39@@ -642,6 +642,10 @@
40
41 `fromExample` allows the creation of a matcher from a prototype object and
42 then modified versions can be created with `update`.
43+
44+ `byEquality` creates a matcher in much the same way as the constructor,
45+ except that the matcher for each of the attributes is assumed to be
46+ `Equals`.
47 """
48
49 def __init__(self, **kwargs):
50@@ -652,6 +656,15 @@
51 self.kws = kwargs
52
53 @classmethod
54+ def byEquality(cls, **kwargs):
55+ """Matches an object where the attributes equal the keyword values.
56+
57+ Similar to the constructor, except that the matcher is assumed to be
58+ Equals.
59+ """
60+ return cls(**dict((name, Equals(value)) for name, value in kwargs.items()))
61+
62+ @classmethod
63 def fromExample(cls, example, *attributes):
64 kwargs = {}
65 for attr in attributes:
66
67=== modified file 'testtools/tests/test_matchers.py'
68--- testtools/tests/test_matchers.py 2011-07-11 10:26:05 +0000
69+++ testtools/tests/test_matchers.py 2011-07-19 15:38:31 +0000
70@@ -583,6 +583,11 @@
71 self.SimpleClass(1, 2),
72 MatchesStructure.fromExample(self.SimpleClass(1, 3), 'x'))
73
74+ def test_byEquality(self):
75+ self.assertThat(
76+ self.SimpleClass(1, 2),
77+ MatchesStructure.byEquality(x=1))
78+
79 def test_update(self):
80 self.assertThat(
81 self.SimpleClass(1, 2),

Subscribers

People subscribed via source and target branches