Merge lp:~lifeless/testtools/bug-683332 into lp:~testtools-committers/testtools/trunk

Proposed by Robert Collins
Status: Merged
Merged at revision: 150
Proposed branch: lp:~lifeless/testtools/bug-683332
Merge into: lp:~testtools-committers/testtools/trunk
Diff against target: 210 lines (+46/-25)
3 files modified
NEWS (+10/-2)
testtools/testresult/real.py (+12/-15)
testtools/tests/test_testresult.py (+24/-8)
To merge this branch: bzr merge lp:~lifeless/testtools/bug-683332
Reviewer Review Type Date Requested Status
Jelmer Vernooij code Approve
testtools developers Pending
Review via email: mp+42751@code.launchpad.net

Description of the change

Fix bug. Yay.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) :
review: Approve (code)
Revision history for this message
Robert Collins (lifeless) wrote :

Landing this as a timeout.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'NEWS'
--- NEWS 2010-11-29 23:46:10 +0000
+++ NEWS 2010-12-04 21:08:52 +0000
@@ -10,10 +10,18 @@
10* addUnexpectedSuccess is translated to addFailure for test results that don't10* addUnexpectedSuccess is translated to addFailure for test results that don't
11 know about addUnexpectedSuccess. Further, it fails the entire result for11 know about addUnexpectedSuccess. Further, it fails the entire result for
12 all testtools TestResults (i.e. wasSuccessful() returns False after12 all testtools TestResults (i.e. wasSuccessful() returns False after
13 addUnexpectedSuccess has been called). (Jonathan Lange, #654474)13 addUnexpectedSuccess has been called). Note that when using a delegating
14 result such as ThreadsafeForwardingResult, MultiTestResult or
15 ExtendedToOriginalDecorator then the behaviour of addUnexpectedSuccess is
16 determined by the delegated to result(s).
17 (Jonathan Lange, Robert Collins, #654474, #683332)
1418
15* startTestRun will reset any errors on the result. That is, wasSuccessful()19* startTestRun will reset any errors on the result. That is, wasSuccessful()
16 will always return True immediately after startTestRun() is called.20 will always return True immediately after startTestRun() is called. This
21 only applies to delegated test results (ThreadsafeForwardingResult,
22 MultiTestResult and ExtendedToOriginalDecorator) if the delegated to result
23 is a testtools test result - we cannot reliably reset the state of unknown
24 test result class instances. (Jonathan Lange, Robert Collins, #683332)
1725
18* Responsibility for running test cleanups has been moved to ``RunTest``.26* Responsibility for running test cleanups has been moved to ``RunTest``.
19 This change does not affect public APIs and can be safely ignored by test27 This change does not affect public APIs and can be safely ignored by test
2028
=== modified file 'testtools/testresult/real.py'
--- testtools/testresult/real.py 2010-11-30 12:54:20 +0000
+++ testtools/testresult/real.py 2010-12-04 21:08:52 +0000
@@ -35,13 +35,11 @@
35 """35 """
3636
37 def __init__(self):37 def __init__(self):
38 super(TestResult, self).__init__()38 # startTestRun resets all attributes, and older clients don't know to
39 self.skip_reasons = {}39 # call startTestRun, so it is called once here.
40 self.__now = None40 # Because subclasses may reasonably not expect this, we call the
41 # -- Start: As per python 2.7 --41 # specific version we want to run.
42 self.expectedFailures = []42 TestResult.startTestRun(self)
43 self.unexpectedSuccesses = []
44 # -- End: As per python 2.7 --
4543
46 def addExpectedFailure(self, test, err=None, details=None):44 def addExpectedFailure(self, test, err=None, details=None):
47 """Called when a test has failed in an expected manner.45 """Called when a test has failed in an expected manner.
@@ -160,9 +158,13 @@
160158
161 New in python 2.7159 New in python 2.7
162 """160 """
161 super(TestResult, self).__init__()
162 self.skip_reasons = {}
163 self.__now = None
164 # -- Start: As per python 2.7 --
165 self.expectedFailures = []
163 self.unexpectedSuccesses = []166 self.unexpectedSuccesses = []
164 self.errors = []167 # -- End: As per python 2.7 --
165 self.failures = []
166168
167 def stopTestRun(self):169 def stopTestRun(self):
168 """Called after a test run completes170 """Called after a test run completes
@@ -406,13 +408,11 @@
406408
407 def __init__(self, decorated):409 def __init__(self, decorated):
408 self.decorated = decorated410 self.decorated = decorated
409 self._was_successful = True
410411
411 def __getattr__(self, name):412 def __getattr__(self, name):
412 return getattr(self.decorated, name)413 return getattr(self.decorated, name)
413414
414 def addError(self, test, err=None, details=None):415 def addError(self, test, err=None, details=None):
415 self._was_successful = False
416 self._check_args(err, details)416 self._check_args(err, details)
417 if details is not None:417 if details is not None:
418 try:418 try:
@@ -437,7 +437,6 @@
437 return addExpectedFailure(test, err)437 return addExpectedFailure(test, err)
438438
439 def addFailure(self, test, err=None, details=None):439 def addFailure(self, test, err=None, details=None):
440 self._was_successful = False
441 self._check_args(err, details)440 self._check_args(err, details)
442 if details is not None:441 if details is not None:
443 try:442 try:
@@ -464,7 +463,6 @@
464 return addSkip(test, reason)463 return addSkip(test, reason)
465464
466 def addUnexpectedSuccess(self, test, details=None):465 def addUnexpectedSuccess(self, test, details=None):
467 self._was_successful = False
468 outcome = getattr(self.decorated, 'addUnexpectedSuccess', None)466 outcome = getattr(self.decorated, 'addUnexpectedSuccess', None)
469 if outcome is None:467 if outcome is None:
470 try:468 try:
@@ -521,7 +519,6 @@
521 return self.decorated.startTest(test)519 return self.decorated.startTest(test)
522520
523 def startTestRun(self):521 def startTestRun(self):
524 self._was_successful = True
525 try:522 try:
526 return self.decorated.startTestRun()523 return self.decorated.startTestRun()
527 except AttributeError:524 except AttributeError:
@@ -552,7 +549,7 @@
552 return method(a_datetime)549 return method(a_datetime)
553550
554 def wasSuccessful(self):551 def wasSuccessful(self):
555 return self._was_successful552 return self.decorated.wasSuccessful()
556553
557554
558class _StringException(Exception):555class _StringException(Exception):
559556
=== modified file 'testtools/tests/test_testresult.py'
--- testtools/tests/test_testresult.py 2010-11-29 00:32:53 +0000
+++ testtools/tests/test_testresult.py 2010-12-04 21:08:52 +0000
@@ -132,7 +132,7 @@
132 result.stopTestRun()132 result.stopTestRun()
133133
134134
135class TestResultContract(Python27Contract):135class DetailsContract(Python27Contract):
136 """Tests for the contract of TestResults."""136 """Tests for the contract of TestResults."""
137137
138 def test_addExpectedFailure_details(self):138 def test_addExpectedFailure_details(self):
@@ -171,6 +171,13 @@
171 result.startTest(self)171 result.startTest(self)
172 result.addSuccess(self, details={})172 result.addSuccess(self, details={})
173173
174
175class FallbackContract(DetailsContract):
176 """When we fallback we take our policy choice to map calls.
177
178 For instance, we map unexpectedSuccess to an error code, not to success.
179 """
180
174 def test_addUnexpectedSuccess_was_successful(self):181 def test_addUnexpectedSuccess_was_successful(self):
175 # addUnexpectedSuccess fails test run in testtools.182 # addUnexpectedSuccess fails test run in testtools.
176 result = self.makeResult()183 result = self.makeResult()
@@ -179,6 +186,14 @@
179 result.stopTest(self)186 result.stopTest(self)
180 self.assertFalse(result.wasSuccessful())187 self.assertFalse(result.wasSuccessful())
181188
189
190class StartTestRunContract(FallbackContract):
191 """Defines the contract for testtools policy choices.
192
193 That is things which are not simply extensions to unittest but choices we
194 have made differently.
195 """
196
182 def test_startTestRun_resets_unexpected_success(self):197 def test_startTestRun_resets_unexpected_success(self):
183 result = self.makeResult()198 result = self.makeResult()
184 result.startTest(self)199 result.startTest(self)
@@ -203,25 +218,26 @@
203 result.startTestRun()218 result.startTestRun()
204 self.assertTrue(result.wasSuccessful())219 self.assertTrue(result.wasSuccessful())
205220
206class TestTestResultContract(TestCase, TestResultContract):221
222class TestTestResultContract(TestCase, StartTestRunContract):
207223
208 def makeResult(self):224 def makeResult(self):
209 return TestResult()225 return TestResult()
210226
211227
212class TestMultiTestResultContract(TestCase, TestResultContract):228class TestMultiTestResultContract(TestCase, StartTestRunContract):
213229
214 def makeResult(self):230 def makeResult(self):
215 return MultiTestResult(TestResult(), TestResult())231 return MultiTestResult(TestResult(), TestResult())
216232
217233
218class TestTextTestResultContract(TestCase, TestResultContract):234class TestTextTestResultContract(TestCase, StartTestRunContract):
219235
220 def makeResult(self):236 def makeResult(self):
221 return TextTestResult(StringIO())237 return TextTestResult(StringIO())
222238
223239
224class TestThreadSafeForwardingResultContract(TestCase, TestResultContract):240class TestThreadSafeForwardingResultContract(TestCase, StartTestRunContract):
225241
226 def makeResult(self):242 def makeResult(self):
227 result_semaphore = threading.Semaphore(1)243 result_semaphore = threading.Semaphore(1)
@@ -229,7 +245,7 @@
229 return ThreadsafeForwardingResult(target, result_semaphore)245 return ThreadsafeForwardingResult(target, result_semaphore)
230246
231247
232class TestExtendedTestResultContract(TestCase, TestResultContract):248class TestExtendedTestResultContract(TestCase, StartTestRunContract):
233249
234 def makeResult(self):250 def makeResult(self):
235 return ExtendedTestResult()251 return ExtendedTestResult()
@@ -241,7 +257,7 @@
241 return Python26TestResult()257 return Python26TestResult()
242258
243259
244class TestAdaptedPython26TestResultContract(TestCase, TestResultContract):260class TestAdaptedPython26TestResultContract(TestCase, FallbackContract):
245261
246 def makeResult(self):262 def makeResult(self):
247 return ExtendedToOriginalDecorator(Python26TestResult())263 return ExtendedToOriginalDecorator(Python26TestResult())
@@ -253,7 +269,7 @@
253 return Python27TestResult()269 return Python27TestResult()
254270
255271
256class TestAdaptedPython27TestResultContract(TestCase, TestResultContract):272class TestAdaptedPython27TestResultContract(TestCase, DetailsContract):
257273
258 def makeResult(self):274 def makeResult(self):
259 return ExtendedToOriginalDecorator(Python27TestResult())275 return ExtendedToOriginalDecorator(Python27TestResult())

Subscribers

People subscribed via source and target branches