df15b91244eca33b88192a0004f5d137f3d94444
[kai/samba-autobuild/.git] / lib / testtools / testtools / tests / test_testresult.py
1 # Copyright (c) 2008 Jonathan M. Lange. See LICENSE for details.
2
3 """Test TestResults and related things."""
4
5 __metaclass__ = type
6
7 import datetime
8 try:
9     from cStringIO import StringIO
10 except ImportError:
11     from io import StringIO
12 import doctest
13 import sys
14 import threading
15
16 from testtools import (
17     ExtendedToOriginalDecorator,
18     MultiTestResult,
19     TestCase,
20     TestResult,
21     TextTestResult,
22     ThreadsafeForwardingResult,
23     testresult,
24     )
25 from testtools.content import Content, ContentType
26 from testtools.matchers import DocTestMatches
27 from testtools.utils import _u, _b
28 from testtools.tests.helpers import (
29     LoggingResult,
30     Python26TestResult,
31     Python27TestResult,
32     ExtendedTestResult,
33     an_exc_info
34     )
35
36
37 class TestTestResultContract(TestCase):
38     """Tests for the contract of TestResults."""
39
40     def test_addExpectedFailure(self):
41         # Calling addExpectedFailure(test, exc_info) completes ok.
42         result = self.makeResult()
43         result.addExpectedFailure(self, an_exc_info)
44
45     def test_addExpectedFailure_details(self):
46         # Calling addExpectedFailure(test, details=xxx) completes ok.
47         result = self.makeResult()
48         result.addExpectedFailure(self, details={})
49
50     def test_addError_details(self):
51         # Calling addError(test, details=xxx) completes ok.
52         result = self.makeResult()
53         result.addError(self, details={})
54
55     def test_addFailure_details(self):
56         # Calling addFailure(test, details=xxx) completes ok.
57         result = self.makeResult()
58         result.addFailure(self, details={})
59
60     def test_addSkipped(self):
61         # Calling addSkip(test, reason) completes ok.
62         result = self.makeResult()
63         result.addSkip(self, _u("Skipped for some reason"))
64
65     def test_addSkipped_details(self):
66         # Calling addSkip(test, reason) completes ok.
67         result = self.makeResult()
68         result.addSkip(self, details={})
69
70     def test_addUnexpectedSuccess(self):
71         # Calling addUnexpectedSuccess(test) completes ok.
72         result = self.makeResult()
73         result.addUnexpectedSuccess(self)
74
75     def test_addUnexpectedSuccess_details(self):
76         # Calling addUnexpectedSuccess(test) completes ok.
77         result = self.makeResult()
78         result.addUnexpectedSuccess(self, details={})
79
80     def test_addSuccess_details(self):
81         # Calling addSuccess(test) completes ok.
82         result = self.makeResult()
83         result.addSuccess(self, details={})
84
85     def test_startStopTestRun(self):
86         # Calling startTestRun completes ok.
87         result = self.makeResult()
88         result.startTestRun()
89         result.stopTestRun()
90
91
92 class TestTestResultContract(TestTestResultContract):
93
94     def makeResult(self):
95         return TestResult()
96
97
98 class TestMultiTestresultContract(TestTestResultContract):
99
100     def makeResult(self):
101         return MultiTestResult(TestResult(), TestResult())
102
103
104 class TestTextTestResultContract(TestTestResultContract):
105
106     def makeResult(self):
107         return TextTestResult(StringIO())
108
109
110 class TestThreadSafeForwardingResultContract(TestTestResultContract):
111
112     def makeResult(self):
113         result_semaphore = threading.Semaphore(1)
114         target = TestResult()
115         return ThreadsafeForwardingResult(target, result_semaphore)
116
117
118 class TestTestResult(TestCase):
119     """Tests for `TestResult`."""
120
121     def makeResult(self):
122         """Make an arbitrary result for testing."""
123         return TestResult()
124
125     def test_addSkipped(self):
126         # Calling addSkip on a TestResult records the test that was skipped in
127         # its skip_reasons dict.
128         result = self.makeResult()
129         result.addSkip(self, _u("Skipped for some reason"))
130         self.assertEqual({_u("Skipped for some reason"):[self]},
131             result.skip_reasons)
132         result.addSkip(self, _u("Skipped for some reason"))
133         self.assertEqual({_u("Skipped for some reason"):[self, self]},
134             result.skip_reasons)
135         result.addSkip(self, _u("Skipped for another reason"))
136         self.assertEqual({_u("Skipped for some reason"):[self, self],
137             _u("Skipped for another reason"):[self]},
138             result.skip_reasons)
139
140     def test_now_datetime_now(self):
141         result = self.makeResult()
142         olddatetime = testresult.real.datetime
143         def restore():
144             testresult.real.datetime = olddatetime
145         self.addCleanup(restore)
146         class Module:
147             pass
148         now = datetime.datetime.now()
149         stubdatetime = Module()
150         stubdatetime.datetime = Module()
151         stubdatetime.datetime.now = lambda: now
152         testresult.real.datetime = stubdatetime
153         # Calling _now() looks up the time.
154         self.assertEqual(now, result._now())
155         then = now + datetime.timedelta(0, 1)
156         # Set an explicit datetime, which gets returned from then on.
157         result.time(then)
158         self.assertNotEqual(now, result._now())
159         self.assertEqual(then, result._now())
160         # go back to looking it up.
161         result.time(None)
162         self.assertEqual(now, result._now())
163
164     def test_now_datetime_time(self):
165         result = self.makeResult()
166         now = datetime.datetime.now()
167         result.time(now)
168         self.assertEqual(now, result._now())
169
170
171 class TestWithFakeExceptions(TestCase):
172
173     def makeExceptionInfo(self, exceptionFactory, *args, **kwargs):
174         try:
175             raise exceptionFactory(*args, **kwargs)
176         except:
177             return sys.exc_info()
178
179
180 class TestMultiTestResult(TestWithFakeExceptions):
181     """Tests for `MultiTestResult`."""
182
183     def setUp(self):
184         TestWithFakeExceptions.setUp(self)
185         self.result1 = LoggingResult([])
186         self.result2 = LoggingResult([])
187         self.multiResult = MultiTestResult(self.result1, self.result2)
188
189     def assertResultLogsEqual(self, expectedEvents):
190         """Assert that our test results have received the expected events."""
191         self.assertEqual(expectedEvents, self.result1._events)
192         self.assertEqual(expectedEvents, self.result2._events)
193
194     def test_empty(self):
195         # Initializing a `MultiTestResult` doesn't do anything to its
196         # `TestResult`s.
197         self.assertResultLogsEqual([])
198
199     def test_startTest(self):
200         # Calling `startTest` on a `MultiTestResult` calls `startTest` on all
201         # its `TestResult`s.
202         self.multiResult.startTest(self)
203         self.assertResultLogsEqual([('startTest', self)])
204
205     def test_stopTest(self):
206         # Calling `stopTest` on a `MultiTestResult` calls `stopTest` on all
207         # its `TestResult`s.
208         self.multiResult.stopTest(self)
209         self.assertResultLogsEqual([('stopTest', self)])
210
211     def test_addSkipped(self):
212         # Calling `addSkip` on a `MultiTestResult` calls addSkip on its
213         # results.
214         reason = _u("Skipped for some reason")
215         self.multiResult.addSkip(self, reason)
216         self.assertResultLogsEqual([('addSkip', self, reason)])
217
218     def test_addSuccess(self):
219         # Calling `addSuccess` on a `MultiTestResult` calls `addSuccess` on
220         # all its `TestResult`s.
221         self.multiResult.addSuccess(self)
222         self.assertResultLogsEqual([('addSuccess', self)])
223
224     def test_done(self):
225         # Calling `done` on a `MultiTestResult` calls `done` on all its
226         # `TestResult`s.
227         self.multiResult.done()
228         self.assertResultLogsEqual([('done')])
229
230     def test_addFailure(self):
231         # Calling `addFailure` on a `MultiTestResult` calls `addFailure` on
232         # all its `TestResult`s.
233         exc_info = self.makeExceptionInfo(AssertionError, 'failure')
234         self.multiResult.addFailure(self, exc_info)
235         self.assertResultLogsEqual([('addFailure', self, exc_info)])
236
237     def test_addError(self):
238         # Calling `addError` on a `MultiTestResult` calls `addError` on all
239         # its `TestResult`s.
240         exc_info = self.makeExceptionInfo(RuntimeError, 'error')
241         self.multiResult.addError(self, exc_info)
242         self.assertResultLogsEqual([('addError', self, exc_info)])
243
244     def test_startTestRun(self):
245         # Calling `startTestRun` on a `MultiTestResult` forwards to all its
246         # `TestResult`s.
247         self.multiResult.startTestRun()
248         self.assertResultLogsEqual([('startTestRun')])
249
250     def test_stopTestRun(self):
251         # Calling `stopTestRun` on a `MultiTestResult` forwards to all its
252         # `TestResult`s.
253         self.multiResult.stopTestRun()
254         self.assertResultLogsEqual([('stopTestRun')])
255
256
257 class TestTextTestResult(TestWithFakeExceptions):
258     """Tests for `TextTestResult`."""
259
260     def setUp(self):
261         super(TestTextTestResult, self).setUp()
262         self.result = TextTestResult(StringIO())
263
264     def make_erroring_test(self):
265         class Test(TestCase):
266             def error(self):
267                 1/0
268         return Test("error")
269
270     def make_failing_test(self):
271         class Test(TestCase):
272             def failed(self):
273                 self.fail("yo!")
274         return Test("failed")
275
276     def make_test(self):
277         class Test(TestCase):
278             def test(self):
279                 pass
280         return Test("test")
281
282     def getvalue(self):
283         return self.result.stream.getvalue()
284
285     def test__init_sets_stream(self):
286         result = TextTestResult("fp")
287         self.assertEqual("fp", result.stream)
288
289     def reset_output(self):
290         self.result.stream = StringIO()
291
292     def test_startTestRun(self):
293         self.result.startTestRun()
294         self.assertEqual("Tests running...\n", self.getvalue())
295
296     def test_stopTestRun_count_many(self):
297         test = self.make_test()
298         self.result.startTestRun()
299         self.result.startTest(test)
300         self.result.stopTest(test)
301         self.result.startTest(test)
302         self.result.stopTest(test)
303         self.result.stream = StringIO()
304         self.result.stopTestRun()
305         self.assertThat(self.getvalue(),
306             DocTestMatches("Ran 2 tests in ...s\n...", doctest.ELLIPSIS))
307
308     def test_stopTestRun_count_single(self):
309         test = self.make_test()
310         self.result.startTestRun()
311         self.result.startTest(test)
312         self.result.stopTest(test)
313         self.reset_output()
314         self.result.stopTestRun()
315         self.assertThat(self.getvalue(),
316             DocTestMatches("Ran 1 test in ...s\n\nOK\n", doctest.ELLIPSIS))
317
318     def test_stopTestRun_count_zero(self):
319         self.result.startTestRun()
320         self.reset_output()
321         self.result.stopTestRun()
322         self.assertThat(self.getvalue(),
323             DocTestMatches("Ran 0 tests in ...s\n\nOK\n", doctest.ELLIPSIS))
324
325     def test_stopTestRun_current_time(self):
326         test = self.make_test()
327         now = datetime.datetime.now()
328         self.result.time(now)
329         self.result.startTestRun()
330         self.result.startTest(test)
331         now = now + datetime.timedelta(0, 0, 0, 1)
332         self.result.time(now)
333         self.result.stopTest(test)
334         self.reset_output()
335         self.result.stopTestRun()
336         self.assertThat(self.getvalue(),
337             DocTestMatches("... in 0.001s\n...", doctest.ELLIPSIS))
338
339     def test_stopTestRun_successful(self):
340         self.result.startTestRun()
341         self.result.stopTestRun()
342         self.assertThat(self.getvalue(),
343             DocTestMatches("...\n\nOK\n", doctest.ELLIPSIS))
344
345     def test_stopTestRun_not_successful_failure(self):
346         test = self.make_failing_test()
347         self.result.startTestRun()
348         test.run(self.result)
349         self.result.stopTestRun()
350         self.assertThat(self.getvalue(),
351             DocTestMatches("...\n\nFAILED (failures=1)\n", doctest.ELLIPSIS))
352
353     def test_stopTestRun_not_successful_error(self):
354         test = self.make_erroring_test()
355         self.result.startTestRun()
356         test.run(self.result)
357         self.result.stopTestRun()
358         self.assertThat(self.getvalue(),
359             DocTestMatches("...\n\nFAILED (failures=1)\n", doctest.ELLIPSIS))
360
361     def test_stopTestRun_shows_details(self):
362         self.result.startTestRun()
363         self.make_erroring_test().run(self.result)
364         self.make_failing_test().run(self.result)
365         self.reset_output()
366         self.result.stopTestRun()
367         self.assertThat(self.getvalue(),
368             DocTestMatches("""...======================================================================
369 ERROR: testtools.tests.test_testresult.Test.error
370 ----------------------------------------------------------------------
371 Text attachment: traceback
372 ------------
373 Traceback (most recent call last):
374   File "...testtools...runtest.py", line ..., in _run_user...
375     return fn(*args)
376   File "...testtools...testcase.py", line ..., in _run_test_method
377     testMethod()
378   File "...testtools...tests...test_testresult.py", line ..., in error
379     1/0
380 ZeroDivisionError: int... division or modulo by zero
381 ------------
382 ======================================================================
383 FAIL: testtools.tests.test_testresult.Test.failed
384 ----------------------------------------------------------------------
385 Text attachment: traceback
386 ------------
387 Traceback (most recent call last):
388   File "...testtools...runtest.py", line ..., in _run_user...
389     return fn(*args)
390   File "...testtools...testcase.py", line ..., in _run_test_method
391     testMethod()
392   File "...testtools...tests...test_testresult.py", line ..., in failed
393     self.fail("yo!")
394 AssertionError: yo!
395 ------------
396 ...""", doctest.ELLIPSIS))
397
398
399 class TestThreadSafeForwardingResult(TestWithFakeExceptions):
400     """Tests for `MultiTestResult`."""
401
402     def setUp(self):
403         TestWithFakeExceptions.setUp(self)
404         self.result_semaphore = threading.Semaphore(1)
405         self.target = LoggingResult([])
406         self.result1 = ThreadsafeForwardingResult(self.target,
407             self.result_semaphore)
408
409     def test_nonforwarding_methods(self):
410         # startTest and stopTest are not forwarded because they need to be
411         # batched.
412         self.result1.startTest(self)
413         self.result1.stopTest(self)
414         self.assertEqual([], self.target._events)
415
416     def test_startTestRun(self):
417         self.result1.startTestRun()
418         self.result2 = ThreadsafeForwardingResult(self.target,
419             self.result_semaphore)
420         self.result2.startTestRun()
421         self.assertEqual(["startTestRun", "startTestRun"], self.target._events)
422
423     def test_stopTestRun(self):
424         self.result1.stopTestRun()
425         self.result2 = ThreadsafeForwardingResult(self.target,
426             self.result_semaphore)
427         self.result2.stopTestRun()
428         self.assertEqual(["stopTestRun", "stopTestRun"], self.target._events)
429
430     def test_forwarding_methods(self):
431         # error, failure, skip and success are forwarded in batches.
432         exc_info1 = self.makeExceptionInfo(RuntimeError, 'error')
433         self.result1.addError(self, exc_info1)
434         exc_info2 = self.makeExceptionInfo(AssertionError, 'failure')
435         self.result1.addFailure(self, exc_info2)
436         reason = _u("Skipped for some reason")
437         self.result1.addSkip(self, reason)
438         self.result1.addSuccess(self)
439         self.assertEqual([('startTest', self),
440             ('addError', self, exc_info1),
441             ('stopTest', self),
442             ('startTest', self),
443             ('addFailure', self, exc_info2),
444             ('stopTest', self),
445             ('startTest', self),
446             ('addSkip', self, reason),
447             ('stopTest', self),
448             ('startTest', self),
449             ('addSuccess', self),
450             ('stopTest', self),
451             ], self.target._events)
452
453
454 class TestExtendedToOriginalResultDecoratorBase(TestCase):
455
456     def make_26_result(self):
457         self.result = Python26TestResult()
458         self.make_converter()
459
460     def make_27_result(self):
461         self.result = Python27TestResult()
462         self.make_converter()
463
464     def make_converter(self):
465         self.converter = ExtendedToOriginalDecorator(self.result)
466
467     def make_extended_result(self):
468         self.result = ExtendedTestResult()
469         self.make_converter()
470
471     def check_outcome_details(self, outcome):
472         """Call an outcome with a details dict to be passed through."""
473         # This dict is /not/ convertible - thats deliberate, as it should
474         # not hit the conversion code path.
475         details = {'foo': 'bar'}
476         getattr(self.converter, outcome)(self, details=details)
477         self.assertEqual([(outcome, self, details)], self.result._events)
478
479     def get_details_and_string(self):
480         """Get a details dict and expected string."""
481         text1 = lambda: [_b("1\n2\n")]
482         text2 = lambda: [_b("3\n4\n")]
483         bin1 = lambda: [_b("5\n")]
484         details = {'text 1': Content(ContentType('text', 'plain'), text1),
485             'text 2': Content(ContentType('text', 'strange'), text2),
486             'bin 1': Content(ContentType('application', 'binary'), bin1)}
487         return (details, "Binary content: bin 1\n"
488             "Text attachment: text 1\n------------\n1\n2\n"
489             "------------\nText attachment: text 2\n------------\n"
490             "3\n4\n------------\n")
491
492     def check_outcome_details_to_exec_info(self, outcome, expected=None):
493         """Call an outcome with a details dict to be made into exc_info."""
494         # The conversion is a done using RemoteError and the string contents
495         # of the text types in the details dict.
496         if not expected:
497             expected = outcome
498         details, err_str = self.get_details_and_string()
499         getattr(self.converter, outcome)(self, details=details)
500         err = self.converter._details_to_exc_info(details)
501         self.assertEqual([(expected, self, err)], self.result._events)
502
503     def check_outcome_details_to_nothing(self, outcome, expected=None):
504         """Call an outcome with a details dict to be swallowed."""
505         if not expected:
506             expected = outcome
507         details = {'foo': 'bar'}
508         getattr(self.converter, outcome)(self, details=details)
509         self.assertEqual([(expected, self)], self.result._events)
510
511     def check_outcome_details_to_string(self, outcome):
512         """Call an outcome with a details dict to be stringified."""
513         details, err_str = self.get_details_and_string()
514         getattr(self.converter, outcome)(self, details=details)
515         self.assertEqual([(outcome, self, err_str)], self.result._events)
516
517     def check_outcome_exc_info(self, outcome, expected=None):
518         """Check that calling a legacy outcome still works."""
519         # calling some outcome with the legacy exc_info style api (no keyword
520         # parameters) gets passed through.
521         if not expected:
522             expected = outcome
523         err = sys.exc_info()
524         getattr(self.converter, outcome)(self, err)
525         self.assertEqual([(expected, self, err)], self.result._events)
526
527     def check_outcome_exc_info_to_nothing(self, outcome, expected=None):
528         """Check that calling a legacy outcome on a fallback works."""
529         # calling some outcome with the legacy exc_info style api (no keyword
530         # parameters) gets passed through.
531         if not expected:
532             expected = outcome
533         err = sys.exc_info()
534         getattr(self.converter, outcome)(self, err)
535         self.assertEqual([(expected, self)], self.result._events)
536
537     def check_outcome_nothing(self, outcome, expected=None):
538         """Check that calling a legacy outcome still works."""
539         if not expected:
540             expected = outcome
541         getattr(self.converter, outcome)(self)
542         self.assertEqual([(expected, self)], self.result._events)
543
544     def check_outcome_string_nothing(self, outcome, expected):
545         """Check that calling outcome with a string calls expected."""
546         getattr(self.converter, outcome)(self, "foo")
547         self.assertEqual([(expected, self)], self.result._events)
548
549     def check_outcome_string(self, outcome):
550         """Check that calling outcome with a string works."""
551         getattr(self.converter, outcome)(self, "foo")
552         self.assertEqual([(outcome, self, "foo")], self.result._events)
553
554
555 class TestExtendedToOriginalResultDecorator(
556     TestExtendedToOriginalResultDecoratorBase):
557
558     def test_progress_py26(self):
559         self.make_26_result()
560         self.converter.progress(1, 2)
561
562     def test_progress_py27(self):
563         self.make_27_result()
564         self.converter.progress(1, 2)
565
566     def test_progress_pyextended(self):
567         self.make_extended_result()
568         self.converter.progress(1, 2)
569         self.assertEqual([('progress', 1, 2)], self.result._events)
570
571     def test_shouldStop(self):
572         self.make_26_result()
573         self.assertEqual(False, self.converter.shouldStop)
574         self.converter.decorated.stop()
575         self.assertEqual(True, self.converter.shouldStop)
576
577     def test_startTest_py26(self):
578         self.make_26_result()
579         self.converter.startTest(self)
580         self.assertEqual([('startTest', self)], self.result._events)
581     
582     def test_startTest_py27(self):
583         self.make_27_result()
584         self.converter.startTest(self)
585         self.assertEqual([('startTest', self)], self.result._events)
586
587     def test_startTest_pyextended(self):
588         self.make_extended_result()
589         self.converter.startTest(self)
590         self.assertEqual([('startTest', self)], self.result._events)
591
592     def test_startTestRun_py26(self):
593         self.make_26_result()
594         self.converter.startTestRun()
595         self.assertEqual([], self.result._events)
596     
597     def test_startTestRun_py27(self):
598         self.make_27_result()
599         self.converter.startTestRun()
600         self.assertEqual([('startTestRun',)], self.result._events)
601
602     def test_startTestRun_pyextended(self):
603         self.make_extended_result()
604         self.converter.startTestRun()
605         self.assertEqual([('startTestRun',)], self.result._events)
606
607     def test_stopTest_py26(self):
608         self.make_26_result()
609         self.converter.stopTest(self)
610         self.assertEqual([('stopTest', self)], self.result._events)
611     
612     def test_stopTest_py27(self):
613         self.make_27_result()
614         self.converter.stopTest(self)
615         self.assertEqual([('stopTest', self)], self.result._events)
616
617     def test_stopTest_pyextended(self):
618         self.make_extended_result()
619         self.converter.stopTest(self)
620         self.assertEqual([('stopTest', self)], self.result._events)
621
622     def test_stopTestRun_py26(self):
623         self.make_26_result()
624         self.converter.stopTestRun()
625         self.assertEqual([], self.result._events)
626     
627     def test_stopTestRun_py27(self):
628         self.make_27_result()
629         self.converter.stopTestRun()
630         self.assertEqual([('stopTestRun',)], self.result._events)
631
632     def test_stopTestRun_pyextended(self):
633         self.make_extended_result()
634         self.converter.stopTestRun()
635         self.assertEqual([('stopTestRun',)], self.result._events)
636
637     def test_tags_py26(self):
638         self.make_26_result()
639         self.converter.tags(1, 2)
640
641     def test_tags_py27(self):
642         self.make_27_result()
643         self.converter.tags(1, 2)
644
645     def test_tags_pyextended(self):
646         self.make_extended_result()
647         self.converter.tags(1, 2)
648         self.assertEqual([('tags', 1, 2)], self.result._events)
649
650     def test_time_py26(self):
651         self.make_26_result()
652         self.converter.time(1)
653
654     def test_time_py27(self):
655         self.make_27_result()
656         self.converter.time(1)
657
658     def test_time_pyextended(self):
659         self.make_extended_result()
660         self.converter.time(1)
661         self.assertEqual([('time', 1)], self.result._events)
662
663
664 class TestExtendedToOriginalAddError(TestExtendedToOriginalResultDecoratorBase):
665
666     outcome = 'addError'
667
668     def test_outcome_Original_py26(self):
669         self.make_26_result()
670         self.check_outcome_exc_info(self.outcome)
671     
672     def test_outcome_Original_py27(self):
673         self.make_27_result()
674         self.check_outcome_exc_info(self.outcome)
675
676     def test_outcome_Original_pyextended(self):
677         self.make_extended_result()
678         self.check_outcome_exc_info(self.outcome)
679
680     def test_outcome_Extended_py26(self):
681         self.make_26_result()
682         self.check_outcome_details_to_exec_info(self.outcome)
683     
684     def test_outcome_Extended_py27(self):
685         self.make_27_result()
686         self.check_outcome_details_to_exec_info(self.outcome)
687
688     def test_outcome_Extended_pyextended(self):
689         self.make_extended_result()
690         self.check_outcome_details(self.outcome)
691
692     def test_outcome__no_details(self):
693         self.make_extended_result()
694         self.assertRaises(ValueError,
695             getattr(self.converter, self.outcome), self)
696
697
698 class TestExtendedToOriginalAddFailure(
699     TestExtendedToOriginalAddError):
700
701     outcome = 'addFailure'
702
703
704 class TestExtendedToOriginalAddExpectedFailure(
705     TestExtendedToOriginalAddError):
706
707     outcome = 'addExpectedFailure'
708
709     def test_outcome_Original_py26(self):
710         self.make_26_result()
711         self.check_outcome_exc_info_to_nothing(self.outcome, 'addSuccess')
712     
713     def test_outcome_Extended_py26(self):
714         self.make_26_result()
715         self.check_outcome_details_to_nothing(self.outcome, 'addSuccess')
716     
717
718
719 class TestExtendedToOriginalAddSkip(
720     TestExtendedToOriginalResultDecoratorBase):
721
722     outcome = 'addSkip'
723
724     def test_outcome_Original_py26(self):
725         self.make_26_result()
726         self.check_outcome_string_nothing(self.outcome, 'addSuccess')
727     
728     def test_outcome_Original_py27(self):
729         self.make_27_result()
730         self.check_outcome_string(self.outcome)
731
732     def test_outcome_Original_pyextended(self):
733         self.make_extended_result()
734         self.check_outcome_string(self.outcome)
735
736     def test_outcome_Extended_py26(self):
737         self.make_26_result()
738         self.check_outcome_string_nothing(self.outcome, 'addSuccess')
739     
740     def test_outcome_Extended_py27(self):
741         self.make_27_result()
742         self.check_outcome_details_to_string(self.outcome)
743
744     def test_outcome_Extended_pyextended(self):
745         self.make_extended_result()
746         self.check_outcome_details(self.outcome)
747
748     def test_outcome__no_details(self):
749         self.make_extended_result()
750         self.assertRaises(ValueError,
751             getattr(self.converter, self.outcome), self)
752
753
754 class TestExtendedToOriginalAddSuccess(
755     TestExtendedToOriginalResultDecoratorBase):
756
757     outcome = 'addSuccess'
758     expected = 'addSuccess'
759
760     def test_outcome_Original_py26(self):
761         self.make_26_result()
762         self.check_outcome_nothing(self.outcome, self.expected)
763     
764     def test_outcome_Original_py27(self):
765         self.make_27_result()
766         self.check_outcome_nothing(self.outcome)
767
768     def test_outcome_Original_pyextended(self):
769         self.make_extended_result()
770         self.check_outcome_nothing(self.outcome)
771
772     def test_outcome_Extended_py26(self):
773         self.make_26_result()
774         self.check_outcome_details_to_nothing(self.outcome, self.expected)
775     
776     def test_outcome_Extended_py27(self):
777         self.make_27_result()
778         self.check_outcome_details_to_nothing(self.outcome)
779
780     def test_outcome_Extended_pyextended(self):
781         self.make_extended_result()
782         self.check_outcome_details(self.outcome)
783
784
785 class TestExtendedToOriginalAddUnexpectedSuccess(
786     TestExtendedToOriginalAddSuccess):
787
788     outcome = 'addUnexpectedSuccess'
789
790
791 class TestExtendedToOriginalResultOtherAttributes(
792     TestExtendedToOriginalResultDecoratorBase):
793
794     def test_other_attribute(self):
795         class OtherExtendedResult:
796             def foo(self):
797                 return 2
798             bar = 1
799         self.result = OtherExtendedResult()
800         self.make_converter()
801         self.assertEqual(1, self.converter.bar)
802         self.assertEqual(2, self.converter.foo())
803     
804
805 def test_suite():
806     from unittest import TestLoader
807     return TestLoader().loadTestsFromName(__name__)