Merge lp:~jml/testtools/basic-mismatch into lp:~testtools-committers/testtools/trunk

Proposed by Jonathan Lange
Status: Merged
Merged at revision: 94
Proposed branch: lp:~jml/testtools/basic-mismatch
Merge into: lp:~testtools-committers/testtools/trunk
Diff against target: 98 lines (+37/-3)
3 files modified
NEWS (+4/-1)
testtools/matchers.py (+19/-2)
testtools/tests/test_matchers.py (+14/-0)
To merge this branch: bzr merge lp:~jml/testtools/basic-mismatch
Reviewer Review Type Date Requested Status
Māris Fogels (community) Approve
testtools developers Pending
Review via email: mp+32872@code.launchpad.net

Description of the change

This branch changes the base "Mismatch" so that it takes optional description and details parameters.

I wanted to do this because for a lot of Matchers I don't really want to make my own Mismatch subclass and I shouldn't need to.

As for implementation, I've preserved the old API, but am not particularly happy with the gymnastics required to do so. I could have my arm twisted to move the changes out of the base class and into a new class like SimpleMismatch. The reason I didn't is that I think Mismatch("description") is a less surprising API for users than a second class.

Māris points out that with this change, many of the Mismatch classes in testtools.matchers could disappear, along with their nice names.

To post a comment you must log in.
Revision history for this message
Māris Fogels (mars) wrote :

Not a developer, but why did you use getatter() in Mismatch.get_details()? It looks like the constructor guarantees that the object always has a valid ._details attribute.

I think the changes look good.

Maris

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

On Tue, Aug 17, 2010 at 3:41 PM, Māris Fogels <email address hidden> wrote:
> Review: Approve
> Not a developer, but why did you use getatter() in Mismatch.get_details()?  It looks like the constructor guarantees that the object always has a valid ._details attribute.

Not all subclasses upcall. I could change the subclasses in
testtools.matchers, but I can't change the subclasses that other
people have made elsewhere.

Revision history for this message
Robert Collins (lifeless) wrote :

So the whole point of mismatch is to be lazy, to allow calculating the
difference once and showing it later; i agree that much of the time
this is simple and won't be deferred; keeping the ability to do so is
extremely important, and we shouldn't make it hard for folk that do
need custom mismatch classes.

That said, sure, I've no problem with the base class being more helpful.

Deleting stuff will be tricky, we've some users that have used some of
our mismatchers directly.

-Rob

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

The base patch keeps the ability to defer, which I agree is important, and pretty much guaranteed by the interface.

Not planning on deleting mismatches that we have.

You OK for me to merge this?

Revision history for this message
Robert Collins (lifeless) wrote :

sure, you have a +1 from maris ;)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2010-08-05 10:19:28 +0000
3+++ NEWS 2010-08-17 13:15:56 +0000
4@@ -7,6 +7,9 @@
5 Improvements
6 ------------
7
8+ * 'Mismatch' now takes optional description and details parameters, so
9+ custom Matchers aren't compelled to make their own subclass.
10+
11 * jml added a built-in UTF8_TEXT ContentType to make it slightly easier to
12 add details to test results.
13
14@@ -16,7 +19,7 @@
15 * New 'Is' matcher, which lets you assert that a thing is identical to
16 another thing.
17
18- * New 'LessThan' matcher which lets you assert that a thing is less than
19+ * New 'LessThan' matcher which lets you assert that a thing is less than
20 another thing.
21
22 * TestCase now has a 'patch()' method to make it easier to monkey-patching
23
24=== modified file 'testtools/matchers.py'
25--- testtools/matchers.py 2010-08-05 06:20:48 +0000
26+++ testtools/matchers.py 2010-08-17 13:15:56 +0000
27@@ -58,12 +58,29 @@
28 class Mismatch(object):
29 """An object describing a mismatch detected by a Matcher."""
30
31+ def __init__(self, description=None, details=None):
32+ """Construct a `Mismatch`.
33+
34+ :param description: A description to use. If not provided,
35+ `Mismatch.describe` must be implemented.
36+ :param details: Extra details about the mismatch. Defaults
37+ to the empty dict.
38+ """
39+ if description:
40+ self._description = description
41+ if details is None:
42+ details = {}
43+ self._details = details
44+
45 def describe(self):
46 """Describe the mismatch.
47
48 This should be either a human-readable string or castable to a string.
49 """
50- raise NotImplementedError(self.describe_difference)
51+ try:
52+ return self._description
53+ except AttributeError:
54+ raise NotImplementedError(self.describe)
55
56 def get_details(self):
57 """Get extra details about the mismatch.
58@@ -81,7 +98,7 @@
59 to the result. For more information see the API to which items from
60 this dict are passed testtools.TestCase.addDetail.
61 """
62- return {}
63+ return getattr(self, '_details', {})
64
65
66 class DocTestMatches(object):
67
68=== modified file 'testtools/tests/test_matchers.py'
69--- testtools/tests/test_matchers.py 2010-08-05 06:20:48 +0000
70+++ testtools/tests/test_matchers.py 2010-08-17 13:15:56 +0000
71@@ -16,6 +16,7 @@
72 LessThan,
73 MatchesAny,
74 MatchesAll,
75+ Mismatch,
76 Not,
77 NotEquals,
78 )
79@@ -24,6 +25,19 @@
80 Matcher
81
82
83+class TestMismatch(TestCase):
84+
85+ def test_constructor_arguments(self):
86+ mismatch = Mismatch("some description", {'detail': "things"})
87+ self.assertEqual("some description", mismatch.describe())
88+ self.assertEqual({'detail': "things"}, mismatch.get_details())
89+
90+ def test_constructor_no_arguments(self):
91+ mismatch = Mismatch()
92+ self.assertRaises(NotImplementedError, mismatch.describe)
93+ self.assertEqual({}, mismatch.get_details())
94+
95+
96 class TestMatchersInterface(object):
97
98 def test_matches_match(self):

Subscribers

People subscribed via source and target branches