57c3293c09fcaa7f69c9ffe0ebd72f033d1f4f95
[nivanova/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 codecs
8 import datetime
9 import doctest
10 import os
11 import shutil
12 import sys
13 import tempfile
14 import threading
15 import warnings
16
17 from testtools import (
18     ExtendedToOriginalDecorator,
19     MultiTestResult,
20     TestCase,
21     TestResult,
22     TextTestResult,
23     ThreadsafeForwardingResult,
24     testresult,
25     try_imports,
26     )
27 from testtools.compat import (
28     _b,
29     _get_exception_encoding,
30     _r,
31     _u,
32     str_is_unicode,
33     )
34 from testtools.content import Content
35 from testtools.content_type import ContentType, UTF8_TEXT
36 from testtools.matchers import (
37     DocTestMatches,
38     MatchesException,
39     Raises,
40     )
41 from testtools.tests.helpers import (
42     LoggingResult,
43     Python26TestResult,
44     Python27TestResult,
45     ExtendedTestResult,
46     an_exc_info
47     )
48 from testtools.testresult.real import utc
49
50 StringIO = try_imports(['StringIO.StringIO', 'io.StringIO'])
51
52
53 class Python26Contract(object):
54
55     def test_fresh_result_is_successful(self):
56         # A result is considered successful before any tests are run.
57         result = self.makeResult()
58         self.assertTrue(result.wasSuccessful())
59
60     def test_addError_is_failure(self):
61         # addError fails the test run.
62         result = self.makeResult()
63         result.startTest(self)
64         result.addError(self, an_exc_info)
65         result.stopTest(self)
66         self.assertFalse(result.wasSuccessful())
67
68     def test_addFailure_is_failure(self):
69         # addFailure fails the test run.
70         result = self.makeResult()
71         result.startTest(self)
72         result.addFailure(self, an_exc_info)
73         result.stopTest(self)
74         self.assertFalse(result.wasSuccessful())
75
76     def test_addSuccess_is_success(self):
77         # addSuccess does not fail the test run.
78         result = self.makeResult()
79         result.startTest(self)
80         result.addSuccess(self)
81         result.stopTest(self)
82         self.assertTrue(result.wasSuccessful())
83
84
85 class Python27Contract(Python26Contract):
86
87     def test_addExpectedFailure(self):
88         # Calling addExpectedFailure(test, exc_info) completes ok.
89         result = self.makeResult()
90         result.startTest(self)
91         result.addExpectedFailure(self, an_exc_info)
92
93     def test_addExpectedFailure_is_success(self):
94         # addExpectedFailure does not fail the test run.
95         result = self.makeResult()
96         result.startTest(self)
97         result.addExpectedFailure(self, an_exc_info)
98         result.stopTest(self)
99         self.assertTrue(result.wasSuccessful())
100
101     def test_addSkipped(self):
102         # Calling addSkip(test, reason) completes ok.
103         result = self.makeResult()
104         result.startTest(self)
105         result.addSkip(self, _u("Skipped for some reason"))
106
107     def test_addSkip_is_success(self):
108         # addSkip does not fail the test run.
109         result = self.makeResult()
110         result.startTest(self)
111         result.addSkip(self, _u("Skipped for some reason"))
112         result.stopTest(self)
113         self.assertTrue(result.wasSuccessful())
114
115     def test_addUnexpectedSuccess(self):
116         # Calling addUnexpectedSuccess(test) completes ok.
117         result = self.makeResult()
118         result.startTest(self)
119         result.addUnexpectedSuccess(self)
120
121     def test_addUnexpectedSuccess_was_successful(self):
122         # addUnexpectedSuccess does not fail the test run in Python 2.7.
123         result = self.makeResult()
124         result.startTest(self)
125         result.addUnexpectedSuccess(self)
126         result.stopTest(self)
127         self.assertTrue(result.wasSuccessful())
128
129     def test_startStopTestRun(self):
130         # Calling startTestRun completes ok.
131         result = self.makeResult()
132         result.startTestRun()
133         result.stopTestRun()
134
135
136 class DetailsContract(Python27Contract):
137     """Tests for the contract of TestResults."""
138
139     def test_addExpectedFailure_details(self):
140         # Calling addExpectedFailure(test, details=xxx) completes ok.
141         result = self.makeResult()
142         result.startTest(self)
143         result.addExpectedFailure(self, details={})
144
145     def test_addError_details(self):
146         # Calling addError(test, details=xxx) completes ok.
147         result = self.makeResult()
148         result.startTest(self)
149         result.addError(self, details={})
150
151     def test_addFailure_details(self):
152         # Calling addFailure(test, details=xxx) completes ok.
153         result = self.makeResult()
154         result.startTest(self)
155         result.addFailure(self, details={})
156
157     def test_addSkipped_details(self):
158         # Calling addSkip(test, reason) completes ok.
159         result = self.makeResult()
160         result.startTest(self)
161         result.addSkip(self, details={})
162
163     def test_addUnexpectedSuccess_details(self):
164         # Calling addUnexpectedSuccess(test) completes ok.
165         result = self.makeResult()
166         result.startTest(self)
167         result.addUnexpectedSuccess(self, details={})
168
169     def test_addSuccess_details(self):
170         # Calling addSuccess(test) completes ok.
171         result = self.makeResult()
172         result.startTest(self)
173         result.addSuccess(self, details={})
174
175
176 class FallbackContract(DetailsContract):
177     """When we fallback we take our policy choice to map calls.
178
179     For instance, we map unexpectedSuccess to an error code, not to success.
180     """
181
182     def test_addUnexpectedSuccess_was_successful(self):
183         # addUnexpectedSuccess fails test run in testtools.
184         result = self.makeResult()
185         result.startTest(self)
186         result.addUnexpectedSuccess(self)
187         result.stopTest(self)
188         self.assertFalse(result.wasSuccessful())
189
190
191 class StartTestRunContract(FallbackContract):
192     """Defines the contract for testtools policy choices.
193     
194     That is things which are not simply extensions to unittest but choices we
195     have made differently.
196     """
197
198     def test_startTestRun_resets_unexpected_success(self):
199         result = self.makeResult()
200         result.startTest(self)
201         result.addUnexpectedSuccess(self)
202         result.stopTest(self)
203         result.startTestRun()
204         self.assertTrue(result.wasSuccessful())
205
206     def test_startTestRun_resets_failure(self):
207         result = self.makeResult()
208         result.startTest(self)
209         result.addFailure(self, an_exc_info)
210         result.stopTest(self)
211         result.startTestRun()
212         self.assertTrue(result.wasSuccessful())
213
214     def test_startTestRun_resets_errors(self):
215         result = self.makeResult()
216         result.startTest(self)
217         result.addError(self, an_exc_info)
218         result.stopTest(self)
219         result.startTestRun()
220         self.assertTrue(result.wasSuccessful())
221
222
223 class TestTestResultContract(TestCase, StartTestRunContract):
224
225     def makeResult(self):
226         return TestResult()
227
228
229 class TestMultiTestResultContract(TestCase, StartTestRunContract):
230
231     def makeResult(self):
232         return MultiTestResult(TestResult(), TestResult())
233
234
235 class TestTextTestResultContract(TestCase, StartTestRunContract):
236
237     def makeResult(self):
238         return TextTestResult(StringIO())
239
240
241 class TestThreadSafeForwardingResultContract(TestCase, StartTestRunContract):
242
243     def makeResult(self):
244         result_semaphore = threading.Semaphore(1)
245         target = TestResult()
246         return ThreadsafeForwardingResult(target, result_semaphore)
247
248
249 class TestExtendedTestResultContract(TestCase, StartTestRunContract):
250
251     def makeResult(self):
252         return ExtendedTestResult()
253
254
255 class TestPython26TestResultContract(TestCase, Python26Contract):
256
257     def makeResult(self):
258         return Python26TestResult()
259
260
261 class TestAdaptedPython26TestResultContract(TestCase, FallbackContract):
262
263     def makeResult(self):
264         return ExtendedToOriginalDecorator(Python26TestResult())
265
266
267 class TestPython27TestResultContract(TestCase, Python27Contract):
268
269     def makeResult(self):
270         return Python27TestResult()
271
272
273 class TestAdaptedPython27TestResultContract(TestCase, DetailsContract):
274
275     def makeResult(self):
276         return ExtendedToOriginalDecorator(Python27TestResult())
277
278
279 class TestTestResult(TestCase):
280     """Tests for `TestResult`."""
281
282     def makeResult(self):
283         """Make an arbitrary result for testing."""
284         return TestResult()
285
286     def test_addSkipped(self):
287         # Calling addSkip on a TestResult records the test that was skipped in
288         # its skip_reasons dict.
289         result = self.makeResult()
290         result.addSkip(self, _u("Skipped for some reason"))
291         self.assertEqual({_u("Skipped for some reason"):[self]},
292             result.skip_reasons)
293         result.addSkip(self, _u("Skipped for some reason"))
294         self.assertEqual({_u("Skipped for some reason"):[self, self]},
295             result.skip_reasons)
296         result.addSkip(self, _u("Skipped for another reason"))
297         self.assertEqual({_u("Skipped for some reason"):[self, self],
298             _u("Skipped for another reason"):[self]},
299             result.skip_reasons)
300
301     def test_now_datetime_now(self):
302         result = self.makeResult()
303         olddatetime = testresult.real.datetime
304         def restore():
305             testresult.real.datetime = olddatetime
306         self.addCleanup(restore)
307         class Module:
308             pass
309         now = datetime.datetime.now(utc)
310         stubdatetime = Module()
311         stubdatetime.datetime = Module()
312         stubdatetime.datetime.now = lambda tz: now
313         testresult.real.datetime = stubdatetime
314         # Calling _now() looks up the time.
315         self.assertEqual(now, result._now())
316         then = now + datetime.timedelta(0, 1)
317         # Set an explicit datetime, which gets returned from then on.
318         result.time(then)
319         self.assertNotEqual(now, result._now())
320         self.assertEqual(then, result._now())
321         # go back to looking it up.
322         result.time(None)
323         self.assertEqual(now, result._now())
324
325     def test_now_datetime_time(self):
326         result = self.makeResult()
327         now = datetime.datetime.now(utc)
328         result.time(now)
329         self.assertEqual(now, result._now())
330
331
332 class TestWithFakeExceptions(TestCase):
333
334     def makeExceptionInfo(self, exceptionFactory, *args, **kwargs):
335         try:
336             raise exceptionFactory(*args, **kwargs)
337         except:
338             return sys.exc_info()
339
340
341 class TestMultiTestResult(TestWithFakeExceptions):
342     """Tests for `MultiTestResult`."""
343
344     def setUp(self):
345         TestWithFakeExceptions.setUp(self)
346         self.result1 = LoggingResult([])
347         self.result2 = LoggingResult([])
348         self.multiResult = MultiTestResult(self.result1, self.result2)
349
350     def assertResultLogsEqual(self, expectedEvents):
351         """Assert that our test results have received the expected events."""
352         self.assertEqual(expectedEvents, self.result1._events)
353         self.assertEqual(expectedEvents, self.result2._events)
354
355     def test_empty(self):
356         # Initializing a `MultiTestResult` doesn't do anything to its
357         # `TestResult`s.
358         self.assertResultLogsEqual([])
359
360     def test_startTest(self):
361         # Calling `startTest` on a `MultiTestResult` calls `startTest` on all
362         # its `TestResult`s.
363         self.multiResult.startTest(self)
364         self.assertResultLogsEqual([('startTest', self)])
365
366     def test_stopTest(self):
367         # Calling `stopTest` on a `MultiTestResult` calls `stopTest` on all
368         # its `TestResult`s.
369         self.multiResult.stopTest(self)
370         self.assertResultLogsEqual([('stopTest', self)])
371
372     def test_addSkipped(self):
373         # Calling `addSkip` on a `MultiTestResult` calls addSkip on its
374         # results.
375         reason = _u("Skipped for some reason")
376         self.multiResult.addSkip(self, reason)
377         self.assertResultLogsEqual([('addSkip', self, reason)])
378
379     def test_addSuccess(self):
380         # Calling `addSuccess` on a `MultiTestResult` calls `addSuccess` on
381         # all its `TestResult`s.
382         self.multiResult.addSuccess(self)
383         self.assertResultLogsEqual([('addSuccess', self)])
384
385     def test_done(self):
386         # Calling `done` on a `MultiTestResult` calls `done` on all its
387         # `TestResult`s.
388         self.multiResult.done()
389         self.assertResultLogsEqual([('done')])
390
391     def test_addFailure(self):
392         # Calling `addFailure` on a `MultiTestResult` calls `addFailure` on
393         # all its `TestResult`s.
394         exc_info = self.makeExceptionInfo(AssertionError, 'failure')
395         self.multiResult.addFailure(self, exc_info)
396         self.assertResultLogsEqual([('addFailure', self, exc_info)])
397
398     def test_addError(self):
399         # Calling `addError` on a `MultiTestResult` calls `addError` on all
400         # its `TestResult`s.
401         exc_info = self.makeExceptionInfo(RuntimeError, 'error')
402         self.multiResult.addError(self, exc_info)
403         self.assertResultLogsEqual([('addError', self, exc_info)])
404
405     def test_startTestRun(self):
406         # Calling `startTestRun` on a `MultiTestResult` forwards to all its
407         # `TestResult`s.
408         self.multiResult.startTestRun()
409         self.assertResultLogsEqual([('startTestRun')])
410
411     def test_stopTestRun(self):
412         # Calling `stopTestRun` on a `MultiTestResult` forwards to all its
413         # `TestResult`s.
414         self.multiResult.stopTestRun()
415         self.assertResultLogsEqual([('stopTestRun')])
416
417     def test_stopTestRun_returns_results(self):
418         # `MultiTestResult.stopTestRun` returns a tuple of all of the return
419         # values the `stopTestRun`s that it forwards to.
420         class Result(LoggingResult):
421             def stopTestRun(self):
422                 super(Result, self).stopTestRun()
423                 return 'foo'
424         multi_result = MultiTestResult(Result([]), Result([]))
425         result = multi_result.stopTestRun()
426         self.assertEqual(('foo', 'foo'), result)
427
428     def test_time(self):
429         # the time call is dispatched, not eaten by the base class
430         self.multiResult.time('foo')
431         self.assertResultLogsEqual([('time', 'foo')])
432
433
434 class TestTextTestResult(TestCase):
435     """Tests for `TextTestResult`."""
436
437     def setUp(self):
438         super(TestTextTestResult, self).setUp()
439         self.result = TextTestResult(StringIO())
440
441     def make_erroring_test(self):
442         class Test(TestCase):
443             def error(self):
444                 1/0
445         return Test("error")
446
447     def make_failing_test(self):
448         class Test(TestCase):
449             def failed(self):
450                 self.fail("yo!")
451         return Test("failed")
452
453     def make_unexpectedly_successful_test(self):
454         class Test(TestCase):
455             def succeeded(self):
456                 self.expectFailure("yo!", lambda: None)
457         return Test("succeeded")
458
459     def make_test(self):
460         class Test(TestCase):
461             def test(self):
462                 pass
463         return Test("test")
464
465     def getvalue(self):
466         return self.result.stream.getvalue()
467
468     def test__init_sets_stream(self):
469         result = TextTestResult("fp")
470         self.assertEqual("fp", result.stream)
471
472     def reset_output(self):
473         self.result.stream = StringIO()
474
475     def test_startTestRun(self):
476         self.result.startTestRun()
477         self.assertEqual("Tests running...\n", self.getvalue())
478
479     def test_stopTestRun_count_many(self):
480         test = self.make_test()
481         self.result.startTestRun()
482         self.result.startTest(test)
483         self.result.stopTest(test)
484         self.result.startTest(test)
485         self.result.stopTest(test)
486         self.result.stream = StringIO()
487         self.result.stopTestRun()
488         self.assertThat(self.getvalue(),
489             DocTestMatches("Ran 2 tests in ...s\n...", doctest.ELLIPSIS))
490
491     def test_stopTestRun_count_single(self):
492         test = self.make_test()
493         self.result.startTestRun()
494         self.result.startTest(test)
495         self.result.stopTest(test)
496         self.reset_output()
497         self.result.stopTestRun()
498         self.assertThat(self.getvalue(),
499             DocTestMatches("Ran 1 test in ...s\n\nOK\n", doctest.ELLIPSIS))
500
501     def test_stopTestRun_count_zero(self):
502         self.result.startTestRun()
503         self.reset_output()
504         self.result.stopTestRun()
505         self.assertThat(self.getvalue(),
506             DocTestMatches("Ran 0 tests in ...s\n\nOK\n", doctest.ELLIPSIS))
507
508     def test_stopTestRun_current_time(self):
509         test = self.make_test()
510         now = datetime.datetime.now(utc)
511         self.result.time(now)
512         self.result.startTestRun()
513         self.result.startTest(test)
514         now = now + datetime.timedelta(0, 0, 0, 1)
515         self.result.time(now)
516         self.result.stopTest(test)
517         self.reset_output()
518         self.result.stopTestRun()
519         self.assertThat(self.getvalue(),
520             DocTestMatches("... in 0.001s\n...", doctest.ELLIPSIS))
521
522     def test_stopTestRun_successful(self):
523         self.result.startTestRun()
524         self.result.stopTestRun()
525         self.assertThat(self.getvalue(),
526             DocTestMatches("...\n\nOK\n", doctest.ELLIPSIS))
527
528     def test_stopTestRun_not_successful_failure(self):
529         test = self.make_failing_test()
530         self.result.startTestRun()
531         test.run(self.result)
532         self.result.stopTestRun()
533         self.assertThat(self.getvalue(),
534             DocTestMatches("...\n\nFAILED (failures=1)\n", doctest.ELLIPSIS))
535
536     def test_stopTestRun_not_successful_error(self):
537         test = self.make_erroring_test()
538         self.result.startTestRun()
539         test.run(self.result)
540         self.result.stopTestRun()
541         self.assertThat(self.getvalue(),
542             DocTestMatches("...\n\nFAILED (failures=1)\n", doctest.ELLIPSIS))
543
544     def test_stopTestRun_not_successful_unexpected_success(self):
545         test = self.make_unexpectedly_successful_test()
546         self.result.startTestRun()
547         test.run(self.result)
548         self.result.stopTestRun()
549         self.assertThat(self.getvalue(),
550             DocTestMatches("...\n\nFAILED (failures=1)\n", doctest.ELLIPSIS))
551
552     def test_stopTestRun_shows_details(self):
553         self.result.startTestRun()
554         self.make_erroring_test().run(self.result)
555         self.make_unexpectedly_successful_test().run(self.result)
556         self.make_failing_test().run(self.result)
557         self.reset_output()
558         self.result.stopTestRun()
559         self.assertThat(self.getvalue(),
560             DocTestMatches("""...======================================================================
561 ERROR: testtools.tests.test_testresult.Test.error
562 ----------------------------------------------------------------------
563 Text attachment: traceback
564 ------------
565 Traceback (most recent call last):
566   File "...testtools...runtest.py", line ..., in _run_user...
567     return fn(*args, **kwargs)
568   File "...testtools...testcase.py", line ..., in _run_test_method
569     return self._get_test_method()()
570   File "...testtools...tests...test_testresult.py", line ..., in error
571     1/0
572 ZeroDivisionError:... divi... by zero...
573 ------------
574 ======================================================================
575 FAIL: testtools.tests.test_testresult.Test.failed
576 ----------------------------------------------------------------------
577 Text attachment: traceback
578 ------------
579 Traceback (most recent call last):
580   File "...testtools...runtest.py", line ..., in _run_user...
581     return fn(*args, **kwargs)
582   File "...testtools...testcase.py", line ..., in _run_test_method
583     return self._get_test_method()()
584   File "...testtools...tests...test_testresult.py", line ..., in failed
585     self.fail("yo!")
586 AssertionError: yo!
587 ------------
588 ======================================================================
589 UNEXPECTED SUCCESS: testtools.tests.test_testresult.Test.succeeded
590 ----------------------------------------------------------------------
591 ...""", doctest.ELLIPSIS | doctest.REPORT_NDIFF))
592
593
594 class TestThreadSafeForwardingResult(TestWithFakeExceptions):
595     """Tests for `TestThreadSafeForwardingResult`."""
596
597     def setUp(self):
598         TestWithFakeExceptions.setUp(self)
599         self.result_semaphore = threading.Semaphore(1)
600         self.target = LoggingResult([])
601         self.result1 = ThreadsafeForwardingResult(self.target,
602             self.result_semaphore)
603
604     def test_nonforwarding_methods(self):
605         # startTest and stopTest are not forwarded because they need to be
606         # batched.
607         self.result1.startTest(self)
608         self.result1.stopTest(self)
609         self.assertEqual([], self.target._events)
610
611     def test_startTestRun(self):
612         self.result1.startTestRun()
613         self.result2 = ThreadsafeForwardingResult(self.target,
614             self.result_semaphore)
615         self.result2.startTestRun()
616         self.assertEqual(["startTestRun", "startTestRun"], self.target._events)
617
618     def test_stopTestRun(self):
619         self.result1.stopTestRun()
620         self.result2 = ThreadsafeForwardingResult(self.target,
621             self.result_semaphore)
622         self.result2.stopTestRun()
623         self.assertEqual(["stopTestRun", "stopTestRun"], self.target._events)
624
625     def test_forwarding_methods(self):
626         # error, failure, skip and success are forwarded in batches.
627         exc_info1 = self.makeExceptionInfo(RuntimeError, 'error')
628         starttime1 = datetime.datetime.utcfromtimestamp(1.489)
629         endtime1 = datetime.datetime.utcfromtimestamp(51.476)
630         self.result1.time(starttime1)
631         self.result1.startTest(self)
632         self.result1.time(endtime1)
633         self.result1.addError(self, exc_info1)
634         exc_info2 = self.makeExceptionInfo(AssertionError, 'failure')
635         starttime2 = datetime.datetime.utcfromtimestamp(2.489)
636         endtime2 = datetime.datetime.utcfromtimestamp(3.476)
637         self.result1.time(starttime2)
638         self.result1.startTest(self)
639         self.result1.time(endtime2)
640         self.result1.addFailure(self, exc_info2)
641         reason = _u("Skipped for some reason")
642         starttime3 = datetime.datetime.utcfromtimestamp(4.489)
643         endtime3 = datetime.datetime.utcfromtimestamp(5.476)
644         self.result1.time(starttime3)
645         self.result1.startTest(self)
646         self.result1.time(endtime3)
647         self.result1.addSkip(self, reason)
648         starttime4 = datetime.datetime.utcfromtimestamp(6.489)
649         endtime4 = datetime.datetime.utcfromtimestamp(7.476)
650         self.result1.time(starttime4)
651         self.result1.startTest(self)
652         self.result1.time(endtime4)
653         self.result1.addSuccess(self)
654         self.assertEqual([
655             ('time', starttime1),
656             ('startTest', self),
657             ('time', endtime1),
658             ('addError', self, exc_info1),
659             ('stopTest', self),
660             ('time', starttime2),
661             ('startTest', self),
662             ('time', endtime2),
663             ('addFailure', self, exc_info2),
664             ('stopTest', self),
665             ('time', starttime3),
666             ('startTest', self),
667             ('time', endtime3),
668             ('addSkip', self, reason),
669             ('stopTest', self),
670             ('time', starttime4),
671             ('startTest', self),
672             ('time', endtime4),
673             ('addSuccess', self),
674             ('stopTest', self),
675             ], self.target._events)
676
677
678 class TestExtendedToOriginalResultDecoratorBase(TestCase):
679
680     def make_26_result(self):
681         self.result = Python26TestResult()
682         self.make_converter()
683
684     def make_27_result(self):
685         self.result = Python27TestResult()
686         self.make_converter()
687
688     def make_converter(self):
689         self.converter = ExtendedToOriginalDecorator(self.result)
690
691     def make_extended_result(self):
692         self.result = ExtendedTestResult()
693         self.make_converter()
694
695     def check_outcome_details(self, outcome):
696         """Call an outcome with a details dict to be passed through."""
697         # This dict is /not/ convertible - thats deliberate, as it should
698         # not hit the conversion code path.
699         details = {'foo': 'bar'}
700         getattr(self.converter, outcome)(self, details=details)
701         self.assertEqual([(outcome, self, details)], self.result._events)
702
703     def get_details_and_string(self):
704         """Get a details dict and expected string."""
705         text1 = lambda: [_b("1\n2\n")]
706         text2 = lambda: [_b("3\n4\n")]
707         bin1 = lambda: [_b("5\n")]
708         details = {'text 1': Content(ContentType('text', 'plain'), text1),
709             'text 2': Content(ContentType('text', 'strange'), text2),
710             'bin 1': Content(ContentType('application', 'binary'), bin1)}
711         return (details, "Binary content: bin 1\n"
712             "Text attachment: text 1\n------------\n1\n2\n"
713             "------------\nText attachment: text 2\n------------\n"
714             "3\n4\n------------\n")
715
716     def check_outcome_details_to_exec_info(self, outcome, expected=None):
717         """Call an outcome with a details dict to be made into exc_info."""
718         # The conversion is a done using RemoteError and the string contents
719         # of the text types in the details dict.
720         if not expected:
721             expected = outcome
722         details, err_str = self.get_details_and_string()
723         getattr(self.converter, outcome)(self, details=details)
724         err = self.converter._details_to_exc_info(details)
725         self.assertEqual([(expected, self, err)], self.result._events)
726
727     def check_outcome_details_to_nothing(self, outcome, expected=None):
728         """Call an outcome with a details dict to be swallowed."""
729         if not expected:
730             expected = outcome
731         details = {'foo': 'bar'}
732         getattr(self.converter, outcome)(self, details=details)
733         self.assertEqual([(expected, self)], self.result._events)
734
735     def check_outcome_details_to_string(self, outcome):
736         """Call an outcome with a details dict to be stringified."""
737         details, err_str = self.get_details_and_string()
738         getattr(self.converter, outcome)(self, details=details)
739         self.assertEqual([(outcome, self, err_str)], self.result._events)
740
741     def check_outcome_details_to_arg(self, outcome, arg, extra_detail=None):
742         """Call an outcome with a details dict to have an arg extracted."""
743         details, _ = self.get_details_and_string()
744         if extra_detail:
745             details.update(extra_detail)
746         getattr(self.converter, outcome)(self, details=details)
747         self.assertEqual([(outcome, self, arg)], self.result._events)
748
749     def check_outcome_exc_info(self, outcome, expected=None):
750         """Check that calling a legacy outcome still works."""
751         # calling some outcome with the legacy exc_info style api (no keyword
752         # parameters) gets passed through.
753         if not expected:
754             expected = outcome
755         err = sys.exc_info()
756         getattr(self.converter, outcome)(self, err)
757         self.assertEqual([(expected, self, err)], self.result._events)
758
759     def check_outcome_exc_info_to_nothing(self, outcome, expected=None):
760         """Check that calling a legacy outcome on a fallback works."""
761         # calling some outcome with the legacy exc_info style api (no keyword
762         # parameters) gets passed through.
763         if not expected:
764             expected = outcome
765         err = sys.exc_info()
766         getattr(self.converter, outcome)(self, err)
767         self.assertEqual([(expected, self)], self.result._events)
768
769     def check_outcome_nothing(self, outcome, expected=None):
770         """Check that calling a legacy outcome still works."""
771         if not expected:
772             expected = outcome
773         getattr(self.converter, outcome)(self)
774         self.assertEqual([(expected, self)], self.result._events)
775
776     def check_outcome_string_nothing(self, outcome, expected):
777         """Check that calling outcome with a string calls expected."""
778         getattr(self.converter, outcome)(self, "foo")
779         self.assertEqual([(expected, self)], self.result._events)
780
781     def check_outcome_string(self, outcome):
782         """Check that calling outcome with a string works."""
783         getattr(self.converter, outcome)(self, "foo")
784         self.assertEqual([(outcome, self, "foo")], self.result._events)
785
786
787 class TestExtendedToOriginalResultDecorator(
788     TestExtendedToOriginalResultDecoratorBase):
789
790     def test_progress_py26(self):
791         self.make_26_result()
792         self.converter.progress(1, 2)
793
794     def test_progress_py27(self):
795         self.make_27_result()
796         self.converter.progress(1, 2)
797
798     def test_progress_pyextended(self):
799         self.make_extended_result()
800         self.converter.progress(1, 2)
801         self.assertEqual([('progress', 1, 2)], self.result._events)
802
803     def test_shouldStop(self):
804         self.make_26_result()
805         self.assertEqual(False, self.converter.shouldStop)
806         self.converter.decorated.stop()
807         self.assertEqual(True, self.converter.shouldStop)
808
809     def test_startTest_py26(self):
810         self.make_26_result()
811         self.converter.startTest(self)
812         self.assertEqual([('startTest', self)], self.result._events)
813
814     def test_startTest_py27(self):
815         self.make_27_result()
816         self.converter.startTest(self)
817         self.assertEqual([('startTest', self)], self.result._events)
818
819     def test_startTest_pyextended(self):
820         self.make_extended_result()
821         self.converter.startTest(self)
822         self.assertEqual([('startTest', self)], self.result._events)
823
824     def test_startTestRun_py26(self):
825         self.make_26_result()
826         self.converter.startTestRun()
827         self.assertEqual([], self.result._events)
828
829     def test_startTestRun_py27(self):
830         self.make_27_result()
831         self.converter.startTestRun()
832         self.assertEqual([('startTestRun',)], self.result._events)
833
834     def test_startTestRun_pyextended(self):
835         self.make_extended_result()
836         self.converter.startTestRun()
837         self.assertEqual([('startTestRun',)], self.result._events)
838
839     def test_stopTest_py26(self):
840         self.make_26_result()
841         self.converter.stopTest(self)
842         self.assertEqual([('stopTest', self)], self.result._events)
843
844     def test_stopTest_py27(self):
845         self.make_27_result()
846         self.converter.stopTest(self)
847         self.assertEqual([('stopTest', self)], self.result._events)
848
849     def test_stopTest_pyextended(self):
850         self.make_extended_result()
851         self.converter.stopTest(self)
852         self.assertEqual([('stopTest', self)], self.result._events)
853
854     def test_stopTestRun_py26(self):
855         self.make_26_result()
856         self.converter.stopTestRun()
857         self.assertEqual([], self.result._events)
858
859     def test_stopTestRun_py27(self):
860         self.make_27_result()
861         self.converter.stopTestRun()
862         self.assertEqual([('stopTestRun',)], self.result._events)
863
864     def test_stopTestRun_pyextended(self):
865         self.make_extended_result()
866         self.converter.stopTestRun()
867         self.assertEqual([('stopTestRun',)], self.result._events)
868
869     def test_tags_py26(self):
870         self.make_26_result()
871         self.converter.tags(1, 2)
872
873     def test_tags_py27(self):
874         self.make_27_result()
875         self.converter.tags(1, 2)
876
877     def test_tags_pyextended(self):
878         self.make_extended_result()
879         self.converter.tags(1, 2)
880         self.assertEqual([('tags', 1, 2)], self.result._events)
881
882     def test_time_py26(self):
883         self.make_26_result()
884         self.converter.time(1)
885
886     def test_time_py27(self):
887         self.make_27_result()
888         self.converter.time(1)
889
890     def test_time_pyextended(self):
891         self.make_extended_result()
892         self.converter.time(1)
893         self.assertEqual([('time', 1)], self.result._events)
894
895
896 class TestExtendedToOriginalAddError(TestExtendedToOriginalResultDecoratorBase):
897
898     outcome = 'addError'
899
900     def test_outcome_Original_py26(self):
901         self.make_26_result()
902         self.check_outcome_exc_info(self.outcome)
903
904     def test_outcome_Original_py27(self):
905         self.make_27_result()
906         self.check_outcome_exc_info(self.outcome)
907
908     def test_outcome_Original_pyextended(self):
909         self.make_extended_result()
910         self.check_outcome_exc_info(self.outcome)
911
912     def test_outcome_Extended_py26(self):
913         self.make_26_result()
914         self.check_outcome_details_to_exec_info(self.outcome)
915
916     def test_outcome_Extended_py27(self):
917         self.make_27_result()
918         self.check_outcome_details_to_exec_info(self.outcome)
919
920     def test_outcome_Extended_pyextended(self):
921         self.make_extended_result()
922         self.check_outcome_details(self.outcome)
923
924     def test_outcome__no_details(self):
925         self.make_extended_result()
926         self.assertThat(
927             lambda: getattr(self.converter, self.outcome)(self),
928             Raises(MatchesException(ValueError)))
929
930
931 class TestExtendedToOriginalAddFailure(
932     TestExtendedToOriginalAddError):
933
934     outcome = 'addFailure'
935
936
937 class TestExtendedToOriginalAddExpectedFailure(
938     TestExtendedToOriginalAddError):
939
940     outcome = 'addExpectedFailure'
941
942     def test_outcome_Original_py26(self):
943         self.make_26_result()
944         self.check_outcome_exc_info_to_nothing(self.outcome, 'addSuccess')
945
946     def test_outcome_Extended_py26(self):
947         self.make_26_result()
948         self.check_outcome_details_to_nothing(self.outcome, 'addSuccess')
949
950
951
952 class TestExtendedToOriginalAddSkip(
953     TestExtendedToOriginalResultDecoratorBase):
954
955     outcome = 'addSkip'
956
957     def test_outcome_Original_py26(self):
958         self.make_26_result()
959         self.check_outcome_string_nothing(self.outcome, 'addSuccess')
960
961     def test_outcome_Original_py27(self):
962         self.make_27_result()
963         self.check_outcome_string(self.outcome)
964
965     def test_outcome_Original_pyextended(self):
966         self.make_extended_result()
967         self.check_outcome_string(self.outcome)
968
969     def test_outcome_Extended_py26(self):
970         self.make_26_result()
971         self.check_outcome_string_nothing(self.outcome, 'addSuccess')
972
973     def test_outcome_Extended_py27_no_reason(self):
974         self.make_27_result()
975         self.check_outcome_details_to_string(self.outcome)
976
977     def test_outcome_Extended_py27_reason(self):
978         self.make_27_result()
979         self.check_outcome_details_to_arg(self.outcome, 'foo',
980             {'reason': Content(UTF8_TEXT, lambda:[_b('foo')])})
981
982     def test_outcome_Extended_pyextended(self):
983         self.make_extended_result()
984         self.check_outcome_details(self.outcome)
985
986     def test_outcome__no_details(self):
987         self.make_extended_result()
988         self.assertThat(
989             lambda: getattr(self.converter, self.outcome)(self),
990             Raises(MatchesException(ValueError)))
991
992
993 class TestExtendedToOriginalAddSuccess(
994     TestExtendedToOriginalResultDecoratorBase):
995
996     outcome = 'addSuccess'
997     expected = 'addSuccess'
998
999     def test_outcome_Original_py26(self):
1000         self.make_26_result()
1001         self.check_outcome_nothing(self.outcome, self.expected)
1002
1003     def test_outcome_Original_py27(self):
1004         self.make_27_result()
1005         self.check_outcome_nothing(self.outcome)
1006
1007     def test_outcome_Original_pyextended(self):
1008         self.make_extended_result()
1009         self.check_outcome_nothing(self.outcome)
1010
1011     def test_outcome_Extended_py26(self):
1012         self.make_26_result()
1013         self.check_outcome_details_to_nothing(self.outcome, self.expected)
1014
1015     def test_outcome_Extended_py27(self):
1016         self.make_27_result()
1017         self.check_outcome_details_to_nothing(self.outcome)
1018
1019     def test_outcome_Extended_pyextended(self):
1020         self.make_extended_result()
1021         self.check_outcome_details(self.outcome)
1022
1023
1024 class TestExtendedToOriginalAddUnexpectedSuccess(
1025     TestExtendedToOriginalResultDecoratorBase):
1026
1027     outcome = 'addUnexpectedSuccess'
1028     expected = 'addFailure'
1029
1030     def test_outcome_Original_py26(self):
1031         self.make_26_result()
1032         getattr(self.converter, self.outcome)(self)
1033         [event] = self.result._events
1034         self.assertEqual((self.expected, self), event[:2])
1035
1036     def test_outcome_Original_py27(self):
1037         self.make_27_result()
1038         self.check_outcome_nothing(self.outcome)
1039
1040     def test_outcome_Original_pyextended(self):
1041         self.make_extended_result()
1042         self.check_outcome_nothing(self.outcome)
1043
1044     def test_outcome_Extended_py26(self):
1045         self.make_26_result()
1046         getattr(self.converter, self.outcome)(self)
1047         [event] = self.result._events
1048         self.assertEqual((self.expected, self), event[:2])
1049
1050     def test_outcome_Extended_py27(self):
1051         self.make_27_result()
1052         self.check_outcome_details_to_nothing(self.outcome)
1053
1054     def test_outcome_Extended_pyextended(self):
1055         self.make_extended_result()
1056         self.check_outcome_details(self.outcome)
1057
1058
1059 class TestExtendedToOriginalResultOtherAttributes(
1060     TestExtendedToOriginalResultDecoratorBase):
1061
1062     def test_other_attribute(self):
1063         class OtherExtendedResult:
1064             def foo(self):
1065                 return 2
1066             bar = 1
1067         self.result = OtherExtendedResult()
1068         self.make_converter()
1069         self.assertEqual(1, self.converter.bar)
1070         self.assertEqual(2, self.converter.foo())
1071
1072
1073 class TestNonAsciiResults(TestCase):
1074     """Test all kinds of tracebacks are cleanly interpreted as unicode
1075
1076     Currently only uses weak "contains" assertions, would be good to be much
1077     stricter about the expected output. This would add a few failures for the
1078     current release of IronPython for instance, which gets some traceback
1079     lines muddled.
1080     """
1081
1082     _sample_texts = (
1083         _u("pa\u026a\u03b8\u0259n"), # Unicode encodings only
1084         _u("\u5357\u7121"), # In ISO 2022 encodings
1085         _u("\xa7\xa7\xa7"), # In ISO 8859 encodings
1086         )
1087     # Everything but Jython shows syntax errors on the current character
1088     _error_on_character = os.name != "java"
1089
1090     def _run(self, stream, test):
1091         """Run the test, the same as in testtools.run but not to stdout"""
1092         result = TextTestResult(stream)
1093         result.startTestRun()
1094         try:
1095             return test.run(result)
1096         finally:
1097             result.stopTestRun()
1098
1099     def _write_module(self, name, encoding, contents):
1100         """Create Python module on disk with contents in given encoding"""
1101         try:
1102             # Need to pre-check that the coding is valid or codecs.open drops
1103             # the file without closing it which breaks non-refcounted pythons
1104             codecs.lookup(encoding)
1105         except LookupError:
1106             self.skip("Encoding unsupported by implementation: %r" % encoding)
1107         f = codecs.open(os.path.join(self.dir, name + ".py"), "w", encoding)
1108         try:
1109             f.write(contents)
1110         finally:
1111             f.close()
1112
1113     def _test_external_case(self, testline, coding="ascii", modulelevel="",
1114             suffix=""):
1115         """Create and run a test case in a seperate module"""
1116         self._setup_external_case(testline, coding, modulelevel, suffix)
1117         return self._run_external_case()
1118
1119     def _setup_external_case(self, testline, coding="ascii", modulelevel="",
1120             suffix=""):
1121         """Create a test case in a seperate module"""
1122         _, prefix, self.modname = self.id().rsplit(".", 2)
1123         self.dir = tempfile.mkdtemp(prefix=prefix, suffix=suffix)
1124         self.addCleanup(shutil.rmtree, self.dir)
1125         self._write_module(self.modname, coding,
1126             # Older Python 2 versions don't see a coding declaration in a
1127             # docstring so it has to be in a comment, but then we can't
1128             # workaround bug: <http://ironpython.codeplex.com/workitem/26940>
1129             "# coding: %s\n"
1130             "import testtools\n"
1131             "%s\n"
1132             "class Test(testtools.TestCase):\n"
1133             "    def runTest(self):\n"
1134             "        %s\n" % (coding, modulelevel, testline))
1135
1136     def _run_external_case(self):
1137         """Run the prepared test case in a seperate module"""
1138         sys.path.insert(0, self.dir)
1139         self.addCleanup(sys.path.remove, self.dir)
1140         module = __import__(self.modname)
1141         self.addCleanup(sys.modules.pop, self.modname)
1142         stream = StringIO()
1143         self._run(stream, module.Test())
1144         return stream.getvalue()
1145
1146     def _silence_deprecation_warnings(self):
1147         """Shut up DeprecationWarning for this test only"""
1148         warnings.simplefilter("ignore", DeprecationWarning)
1149         self.addCleanup(warnings.filters.remove, warnings.filters[0])
1150
1151     def _get_sample_text(self, encoding="unicode_internal"):
1152         if encoding is None and str_is_unicode:
1153            encoding = "unicode_internal"
1154         for u in self._sample_texts:
1155             try:
1156                 b = u.encode(encoding)
1157                 if u == b.decode(encoding):
1158                    if str_is_unicode:
1159                        return u, u
1160                    return u, b
1161             except (LookupError, UnicodeError):
1162                 pass
1163         self.skip("Could not find a sample text for encoding: %r" % encoding)
1164
1165     def _as_output(self, text):
1166         return text
1167
1168     def test_non_ascii_failure_string(self):
1169         """Assertion contents can be non-ascii and should get decoded"""
1170         text, raw = self._get_sample_text(_get_exception_encoding())
1171         textoutput = self._test_external_case("self.fail(%s)" % _r(raw))
1172         self.assertIn(self._as_output(text), textoutput)
1173
1174     def test_non_ascii_failure_string_via_exec(self):
1175         """Assertion via exec can be non-ascii and still gets decoded"""
1176         text, raw = self._get_sample_text(_get_exception_encoding())
1177         textoutput = self._test_external_case(
1178             testline='exec ("self.fail(%s)")' % _r(raw))
1179         self.assertIn(self._as_output(text), textoutput)
1180
1181     def test_control_characters_in_failure_string(self):
1182         """Control characters in assertions should be escaped"""
1183         textoutput = self._test_external_case("self.fail('\\a\\a\\a')")
1184         self.expectFailure("Defense against the beeping horror unimplemented",
1185             self.assertNotIn, self._as_output("\a\a\a"), textoutput)
1186         self.assertIn(self._as_output(_u("\uFFFD\uFFFD\uFFFD")), textoutput)
1187
1188     def test_os_error(self):
1189         """Locale error messages from the OS shouldn't break anything"""
1190         textoutput = self._test_external_case(
1191             modulelevel="import os",
1192             testline="os.mkdir('/')")
1193         if os.name != "nt" or sys.version_info < (2, 5):
1194             self.assertIn(self._as_output("OSError: "), textoutput)
1195         else:
1196             self.assertIn(self._as_output("WindowsError: "), textoutput)
1197
1198     def test_assertion_text_shift_jis(self):
1199         """A terminal raw backslash in an encoded string is weird but fine"""
1200         example_text = _u("\u5341")
1201         textoutput = self._test_external_case(
1202             coding="shift_jis",
1203             testline="self.fail('%s')" % example_text)
1204         if str_is_unicode:
1205             output_text = example_text
1206         else:
1207             output_text = example_text.encode("shift_jis").decode(
1208                 _get_exception_encoding(), "replace")
1209         self.assertIn(self._as_output("AssertionError: %s" % output_text),
1210             textoutput)
1211
1212     def test_file_comment_iso2022_jp(self):
1213         """Control character escapes must be preserved if valid encoding"""
1214         example_text, _ = self._get_sample_text("iso2022_jp")
1215         textoutput = self._test_external_case(
1216             coding="iso2022_jp",
1217             testline="self.fail('Simple') # %s" % example_text)
1218         self.assertIn(self._as_output(example_text), textoutput)
1219
1220     def test_unicode_exception(self):
1221         """Exceptions that can be formated losslessly as unicode should be"""
1222         example_text, _ = self._get_sample_text()
1223         exception_class = (
1224             "class FancyError(Exception):\n"
1225             # A __unicode__ method does nothing on py3k but the default works
1226             "    def __unicode__(self):\n"
1227             "        return self.args[0]\n")
1228         textoutput = self._test_external_case(
1229             modulelevel=exception_class,
1230             testline="raise FancyError(%s)" % _r(example_text))
1231         self.assertIn(self._as_output(example_text), textoutput)
1232
1233     def test_unprintable_exception(self):
1234         """A totally useless exception instance still prints something"""
1235         exception_class = (
1236             "class UnprintableError(Exception):\n"
1237             "    def __str__(self):\n"
1238             "        raise RuntimeError\n"
1239             "    def __unicode__(self):\n"
1240             "        raise RuntimeError\n"
1241             "    def __repr__(self):\n"
1242             "        raise RuntimeError\n")
1243         textoutput = self._test_external_case(
1244             modulelevel=exception_class,
1245             testline="raise UnprintableError")
1246         self.assertIn(self._as_output(
1247             "UnprintableError: <unprintable UnprintableError object>\n"),
1248             textoutput)
1249
1250     def test_string_exception(self):
1251         """Raise a string rather than an exception instance if supported"""
1252         if sys.version_info > (2, 6):
1253             self.skip("No string exceptions in Python 2.6 or later")
1254         elif sys.version_info > (2, 5):
1255             self._silence_deprecation_warnings()
1256         textoutput = self._test_external_case(testline="raise 'plain str'")
1257         self.assertIn(self._as_output("\nplain str\n"), textoutput)
1258
1259     def test_non_ascii_dirname(self):
1260         """Script paths in the traceback can be non-ascii"""
1261         text, raw = self._get_sample_text(sys.getfilesystemencoding())
1262         textoutput = self._test_external_case(
1263             # Avoid bug in Python 3 by giving a unicode source encoding rather
1264             # than just ascii which raises a SyntaxError with no other details
1265             coding="utf-8",
1266             testline="self.fail('Simple')",
1267             suffix=raw)
1268         self.assertIn(self._as_output(text), textoutput)
1269
1270     def test_syntax_error(self):
1271         """Syntax errors should still have fancy special-case formatting"""
1272         textoutput = self._test_external_case("exec ('f(a, b c)')")
1273         self.assertIn(self._as_output(
1274             '  File "<string>", line 1\n'
1275             '    f(a, b c)\n'
1276             + ' ' * self._error_on_character +
1277             '          ^\n'
1278             'SyntaxError: '
1279             ), textoutput)
1280
1281     def test_syntax_error_malformed(self):
1282         """Syntax errors with bogus parameters should break anything"""
1283         textoutput = self._test_external_case("raise SyntaxError(3, 2, 1)")
1284         self.assertIn(self._as_output("\nSyntaxError: "), textoutput)
1285
1286     def test_syntax_error_import_binary(self):
1287         """Importing a binary file shouldn't break SyntaxError formatting"""
1288         if sys.version_info < (2, 5):
1289             # Python 2.4 assumes the file is latin-1 and tells you off
1290             self._silence_deprecation_warnings()
1291         self._setup_external_case("import bad")
1292         f = open(os.path.join(self.dir, "bad.py"), "wb")
1293         try:
1294             f.write(_b("x\x9c\xcb*\xcd\xcb\x06\x00\x04R\x01\xb9"))
1295         finally:
1296             f.close()
1297         textoutput = self._run_external_case()
1298         self.assertIn(self._as_output("\nSyntaxError: "), textoutput)
1299
1300     def test_syntax_error_line_iso_8859_1(self):
1301         """Syntax error on a latin-1 line shows the line decoded"""
1302         text, raw = self._get_sample_text("iso-8859-1")
1303         textoutput = self._setup_external_case("import bad")
1304         self._write_module("bad", "iso-8859-1",
1305             "# coding: iso-8859-1\n! = 0 # %s\n" % text)
1306         textoutput = self._run_external_case()
1307         self.assertIn(self._as_output(_u(
1308             #'bad.py", line 2\n'
1309             '    ! = 0 # %s\n'
1310             '    ^\n'
1311             'SyntaxError: ') %
1312             (text,)), textoutput)
1313
1314     def test_syntax_error_line_iso_8859_5(self):
1315         """Syntax error on a iso-8859-5 line shows the line decoded"""
1316         text, raw = self._get_sample_text("iso-8859-5")
1317         textoutput = self._setup_external_case("import bad")
1318         self._write_module("bad", "iso-8859-5",
1319             "# coding: iso-8859-5\n%% = 0 # %s\n" % text)
1320         textoutput = self._run_external_case()
1321         self.assertIn(self._as_output(_u(
1322             #'bad.py", line 2\n'
1323             '    %% = 0 # %s\n'
1324             + ' ' * self._error_on_character +
1325             '   ^\n'
1326             'SyntaxError: ') %
1327             (text,)), textoutput)
1328
1329     def test_syntax_error_line_euc_jp(self):
1330         """Syntax error on a euc_jp line shows the line decoded"""
1331         text, raw = self._get_sample_text("euc_jp")
1332         textoutput = self._setup_external_case("import bad")
1333         self._write_module("bad", "euc_jp",
1334             "# coding: euc_jp\n$ = 0 # %s\n" % text)
1335         textoutput = self._run_external_case()
1336         self.assertIn(self._as_output(_u(
1337             #'bad.py", line 2\n'
1338             '    $ = 0 # %s\n'
1339             + ' ' * self._error_on_character +
1340             '   ^\n'
1341             'SyntaxError: ') %
1342             (text,)), textoutput)
1343
1344     def test_syntax_error_line_utf_8(self):
1345         """Syntax error on a utf-8 line shows the line decoded"""
1346         text, raw = self._get_sample_text("utf-8")
1347         textoutput = self._setup_external_case("import bad")
1348         self._write_module("bad", "utf-8", _u("\ufeff^ = 0 # %s\n") % text)
1349         textoutput = self._run_external_case()
1350         self.assertIn(self._as_output(_u(
1351             'bad.py", line 1\n'
1352             '    ^ = 0 # %s\n'
1353             + ' ' * self._error_on_character +
1354             '   ^\n'
1355             'SyntaxError: ') %
1356             text), textoutput)
1357
1358
1359 class TestNonAsciiResultsWithUnittest(TestNonAsciiResults):
1360     """Test that running under unittest produces clean ascii strings"""
1361
1362     def _run(self, stream, test):
1363         from unittest import TextTestRunner as _Runner
1364         return _Runner(stream).run(test)
1365
1366     def _as_output(self, text):
1367         if str_is_unicode:
1368             return text
1369         return text.encode("utf-8")
1370
1371
1372 def test_suite():
1373     from unittest import TestLoader
1374     return TestLoader().loadTestsFromName(__name__)