Merge lp:~jml/testtools/assert-is-none-tweaks into lp:~testtools-committers/testtools/trunk

Proposed by Jonathan Lange
Status: Merged
Merged at revision: 195
Proposed branch: lp:~jml/testtools/assert-is-none-tweaks
Merge into: lp:~testtools-committers/testtools/trunk
Diff against target: 226 lines (+86/-8)
5 files modified
NEWS (+9/-2)
testtools/matchers.py (+7/-0)
testtools/testcase.py (+29/-3)
testtools/tests/test_matchers.py (+17/-0)
testtools/tests/test_testtools.py (+24/-3)
To merge this branch: bzr merge lp:~jml/testtools/assert-is-none-tweaks
Reviewer Review Type Date Requested Status
testtools developers Pending
Review via email: mp+65186@code.launchpad.net

Description of the change

Tweaks to ``Annotate`` and the implementation of the built-in assertions, along with some flakes cleanup.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2011-06-12 00:58:39 +0000
3+++ NEWS 2011-06-20 11:59:26 +0000
4@@ -4,6 +4,13 @@
5 NEXT
6 ~~~~
7
8+Improvements
9+------------
10+
11+* New convenience assertions, ``assertIsNone`` and ``assertIsNotNone``.
12+ (Christian Kampka)
13+
14+
15 0.9.11
16 ~~~~~~
17
18@@ -12,7 +19,7 @@
19 outputs and a compat helper for testing libraries that deal with bytestrings.
20
21 Changes
22-~~~~~~~
23+-------
24
25 * ``TestCase`` now uses super to call base ``unittest.TestCase`` constructor,
26 ``setUp`` and ``tearDown``. (Tim Cole, #771508)
27@@ -22,7 +29,7 @@
28
29
30 Improvements
31-~~~~~~~~~~~~
32+------------
33
34 * Additional compat helper for ``BytesIO`` for libraries that build on
35 testtools and are working on Python 3 porting. (Robert Collins)
36
37=== modified file 'testtools/matchers.py'
38--- testtools/matchers.py 2011-04-20 23:45:52 +0000
39+++ testtools/matchers.py 2011-06-20 11:59:26 +0000
40@@ -496,6 +496,13 @@
41 self.annotation = annotation
42 self.matcher = matcher
43
44+ @classmethod
45+ def if_message(cls, annotation, matcher):
46+ """Annotate ``matcher`` only if ``annotation`` is non-empty."""
47+ if not annotation:
48+ return matcher
49+ return cls(annotation, matcher)
50+
51 def __str__(self):
52 return 'Annotate(%r, %s)' % (self.annotation, self.matcher)
53
54
55=== modified file 'testtools/testcase.py'
56--- testtools/testcase.py 2011-05-27 17:00:32 +0000
57+++ testtools/testcase.py 2011-06-20 11:59:26 +0000
58@@ -29,6 +29,8 @@
59 from testtools.matchers import (
60 Annotate,
61 Equals,
62+ Is,
63+ Not,
64 )
65 from testtools.monkey import patch
66 from testtools.runtest import RunTest
67@@ -304,18 +306,35 @@
68 :param observed: The observed value.
69 :param message: An optional message to include in the error.
70 """
71- matcher = Equals(expected)
72- if message:
73- matcher = Annotate(message, matcher)
74+ matcher = Annotate.if_message(message, Equals(expected))
75 self.assertThat(observed, matcher)
76
77 failUnlessEqual = assertEquals = assertEqual
78
79 def assertIn(self, needle, haystack):
80 """Assert that needle is in haystack."""
81+ # XXX: Re-implement with matchers.
82 if needle not in haystack:
83 self.fail('%r not in %r' % (needle, haystack))
84
85+ def assertIsNone(self, observed, message=''):
86+ """Assert that 'observed' is equal to None.
87+
88+ :param observed: The observed value.
89+ :param message: An optional message describing the error.
90+ """
91+ matcher = Annotate.if_message(message, Is(None))
92+ self.assertThat(observed, matcher)
93+
94+ def assertIsNotNone(self, observed, message=''):
95+ """Assert that 'observed' is not equal to None.
96+
97+ :param observed: The observed value.
98+ :param message: An optional message describing the error.
99+ """
100+ matcher = Annotate.if_message(message, Not(Is(None)))
101+ self.assertThat(observed, matcher)
102+
103 def assertIs(self, expected, observed, message=''):
104 """Assert that 'expected' is 'observed'.
105
106@@ -323,6 +342,7 @@
107 :param observed: The observed value.
108 :param message: An optional message describing the error.
109 """
110+ # XXX: Re-implement with matchers.
111 if message:
112 message = ': ' + message
113 if expected is not observed:
114@@ -330,6 +350,7 @@
115
116 def assertIsNot(self, expected, observed, message=''):
117 """Assert that 'expected' is not 'observed'."""
118+ # XXX: Re-implement with matchers.
119 if message:
120 message = ': ' + message
121 if expected is observed:
122@@ -337,10 +358,12 @@
123
124 def assertNotIn(self, needle, haystack):
125 """Assert that needle is not in haystack."""
126+ # XXX: Re-implement with matchers.
127 if needle in haystack:
128 self.fail('%r in %r' % (needle, haystack))
129
130 def assertIsInstance(self, obj, klass, msg=None):
131+ # XXX: Re-implement with matchers.
132 if msg is None:
133 msg = '%r is not an instance of %s' % (
134 obj, self._formatTypes(klass))
135@@ -355,6 +378,7 @@
136 deemed to have suffered an error, exactly as for an
137 unexpected exception.
138 """
139+ # XXX: Re-implement with matchers.
140 try:
141 ret = callableObj(*args, **kwargs)
142 except excClass:
143@@ -371,6 +395,8 @@
144 :param matcher: An object meeting the testtools.Matcher protocol.
145 :raises self.failureException: When matcher does not match thing.
146 """
147+ # XXX: Should this take an optional 'message' parameter? Would kind of
148+ # make sense.
149 mismatch = matcher.match(matchee)
150 if not mismatch:
151 return
152
153=== modified file 'testtools/tests/test_matchers.py'
154--- testtools/tests/test_matchers.py 2011-04-20 23:45:52 +0000
155+++ testtools/tests/test_matchers.py 2011-06-20 11:59:26 +0000
156@@ -336,6 +336,23 @@
157
158 describe_examples = [("1 != 2: foo", 2, Annotate('foo', Equals(1)))]
159
160+ def test_if_message_no_message(self):
161+ # Annotate.if_message returns the given matcher if there is no
162+ # message.
163+ matcher = Equals(1)
164+ not_annotated = Annotate.if_message('', matcher)
165+ self.assertIs(matcher, not_annotated)
166+
167+ def test_if_message_given_message(self):
168+ # Annotate.if_message returns an annotated version of the matcher if a
169+ # message is provided.
170+ matcher = Equals(1)
171+ expected = Annotate('foo', matcher)
172+ annotated = Annotate.if_message('foo', matcher)
173+ self.assertThat(
174+ annotated,
175+ MatchesStructure.fromExample(expected, 'annotation', 'matcher'))
176+
177
178 class TestAnnotatedMismatch(TestCase):
179
180
181=== modified file 'testtools/tests/test_testtools.py'
182--- testtools/tests/test_testtools.py 2011-05-12 23:01:56 +0000
183+++ testtools/tests/test_testtools.py 2011-06-20 11:59:26 +0000
184@@ -1,11 +1,9 @@
185-# Copyright (c) 2008-2010 testtools developers. See LICENSE for details.
186+# Copyright (c) 2008-2011 testtools developers. See LICENSE for details.
187
188 """Tests for extensions to the base test library."""
189
190 from pprint import pformat
191-import os
192 import sys
193-import tempfile
194 import unittest
195
196 from testtools import (
197@@ -501,6 +499,29 @@
198 self.assertFails(expected_error, self.assertEquals, a, b)
199 self.assertFails(expected_error, self.failUnlessEqual, a, b)
200
201+ def test_assertIsNone(self):
202+ self.assertIsNone(None)
203+
204+ expected_error = '\n'.join([
205+ 'Match failed. Matchee: "0"',
206+ 'Matcher: Is(None)',
207+ 'Difference: None is not 0',
208+ ''
209+ ])
210+ self.assertFails(expected_error, self.assertIsNone, 0)
211+
212+ def test_assertIsNotNone(self):
213+ self.assertIsNotNone(0)
214+ self.assertIsNotNone("0")
215+
216+ expected_error = '\n'.join([
217+ 'Match failed. Matchee: "None"',
218+ 'Matcher: Not(Is(None))',
219+ 'Difference: None matches Is(None)',
220+ ''
221+ ])
222+ self.assertFails(expected_error, self.assertIsNotNone, None)
223+
224
225 class TestAddCleanup(TestCase):
226 """Tests for TestCase.addCleanup."""

Subscribers

People subscribed via source and target branches