1 # Copyright (c) 2008 Jonathan M. Lange. See LICENSE for details.
3 """Test TestResults and related things."""
9 from cStringIO import StringIO
11 from io import StringIO
16 from testtools import (
17 ExtendedToOriginalDecorator,
22 ThreadsafeForwardingResult,
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 (
37 class TestTestResultContract(TestCase):
38 """Tests for the contract of TestResults."""
40 def test_addExpectedFailure(self):
41 # Calling addExpectedFailure(test, exc_info) completes ok.
42 result = self.makeResult()
43 result.addExpectedFailure(self, an_exc_info)
45 def test_addExpectedFailure_details(self):
46 # Calling addExpectedFailure(test, details=xxx) completes ok.
47 result = self.makeResult()
48 result.addExpectedFailure(self, details={})
50 def test_addError_details(self):
51 # Calling addError(test, details=xxx) completes ok.
52 result = self.makeResult()
53 result.addError(self, details={})
55 def test_addFailure_details(self):
56 # Calling addFailure(test, details=xxx) completes ok.
57 result = self.makeResult()
58 result.addFailure(self, details={})
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"))
65 def test_addSkipped_details(self):
66 # Calling addSkip(test, reason) completes ok.
67 result = self.makeResult()
68 result.addSkip(self, details={})
70 def test_addUnexpectedSuccess(self):
71 # Calling addUnexpectedSuccess(test) completes ok.
72 result = self.makeResult()
73 result.addUnexpectedSuccess(self)
75 def test_addUnexpectedSuccess_details(self):
76 # Calling addUnexpectedSuccess(test) completes ok.
77 result = self.makeResult()
78 result.addUnexpectedSuccess(self, details={})
80 def test_addSuccess_details(self):
81 # Calling addSuccess(test) completes ok.
82 result = self.makeResult()
83 result.addSuccess(self, details={})
85 def test_startStopTestRun(self):
86 # Calling startTestRun completes ok.
87 result = self.makeResult()
92 class TestTestResultContract(TestTestResultContract):
98 class TestMultiTestresultContract(TestTestResultContract):
100 def makeResult(self):
101 return MultiTestResult(TestResult(), TestResult())
104 class TestTextTestResultContract(TestTestResultContract):
106 def makeResult(self):
107 return TextTestResult(StringIO())
110 class TestThreadSafeForwardingResultContract(TestTestResultContract):
112 def makeResult(self):
113 result_semaphore = threading.Semaphore(1)
114 target = TestResult()
115 return ThreadsafeForwardingResult(target, result_semaphore)
118 class TestTestResult(TestCase):
119 """Tests for `TestResult`."""
121 def makeResult(self):
122 """Make an arbitrary result for testing."""
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]},
132 result.addSkip(self, _u("Skipped for some reason"))
133 self.assertEqual({_u("Skipped for some reason"):[self, self]},
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]},
140 def test_now_datetime_now(self):
141 result = self.makeResult()
142 olddatetime = testresult.real.datetime
144 testresult.real.datetime = olddatetime
145 self.addCleanup(restore)
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.
158 self.assertNotEqual(now, result._now())
159 self.assertEqual(then, result._now())
160 # go back to looking it up.
162 self.assertEqual(now, result._now())
164 def test_now_datetime_time(self):
165 result = self.makeResult()
166 now = datetime.datetime.now()
168 self.assertEqual(now, result._now())
171 class TestWithFakeExceptions(TestCase):
173 def makeExceptionInfo(self, exceptionFactory, *args, **kwargs):
175 raise exceptionFactory(*args, **kwargs)
177 return sys.exc_info()
180 class TestMultiTestResult(TestWithFakeExceptions):
181 """Tests for `MultiTestResult`."""
184 TestWithFakeExceptions.setUp(self)
185 self.result1 = LoggingResult([])
186 self.result2 = LoggingResult([])
187 self.multiResult = MultiTestResult(self.result1, self.result2)
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)
194 def test_empty(self):
195 # Initializing a `MultiTestResult` doesn't do anything to its
197 self.assertResultLogsEqual([])
199 def test_startTest(self):
200 # Calling `startTest` on a `MultiTestResult` calls `startTest` on all
202 self.multiResult.startTest(self)
203 self.assertResultLogsEqual([('startTest', self)])
205 def test_stopTest(self):
206 # Calling `stopTest` on a `MultiTestResult` calls `stopTest` on all
208 self.multiResult.stopTest(self)
209 self.assertResultLogsEqual([('stopTest', self)])
211 def test_addSkipped(self):
212 # Calling `addSkip` on a `MultiTestResult` calls addSkip on its
214 reason = _u("Skipped for some reason")
215 self.multiResult.addSkip(self, reason)
216 self.assertResultLogsEqual([('addSkip', self, reason)])
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)])
225 # Calling `done` on a `MultiTestResult` calls `done` on all its
227 self.multiResult.done()
228 self.assertResultLogsEqual([('done')])
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)])
237 def test_addError(self):
238 # Calling `addError` on a `MultiTestResult` calls `addError` on all
240 exc_info = self.makeExceptionInfo(RuntimeError, 'error')
241 self.multiResult.addError(self, exc_info)
242 self.assertResultLogsEqual([('addError', self, exc_info)])
244 def test_startTestRun(self):
245 # Calling `startTestRun` on a `MultiTestResult` forwards to all its
247 self.multiResult.startTestRun()
248 self.assertResultLogsEqual([('startTestRun')])
250 def test_stopTestRun(self):
251 # Calling `stopTestRun` on a `MultiTestResult` forwards to all its
253 self.multiResult.stopTestRun()
254 self.assertResultLogsEqual([('stopTestRun')])
257 class TestTextTestResult(TestWithFakeExceptions):
258 """Tests for `TextTestResult`."""
261 super(TestTextTestResult, self).setUp()
262 self.result = TextTestResult(StringIO())
264 def make_erroring_test(self):
265 class Test(TestCase):
270 def make_failing_test(self):
271 class Test(TestCase):
274 return Test("failed")
277 class Test(TestCase):
283 return self.result.stream.getvalue()
285 def test__init_sets_stream(self):
286 result = TextTestResult("fp")
287 self.assertEqual("fp", result.stream)
289 def reset_output(self):
290 self.result.stream = StringIO()
292 def test_startTestRun(self):
293 self.result.startTestRun()
294 self.assertEqual("Tests running...\n", self.getvalue())
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))
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)
314 self.result.stopTestRun()
315 self.assertThat(self.getvalue(),
316 DocTestMatches("Ran 1 test in ...s\n\nOK\n", doctest.ELLIPSIS))
318 def test_stopTestRun_count_zero(self):
319 self.result.startTestRun()
321 self.result.stopTestRun()
322 self.assertThat(self.getvalue(),
323 DocTestMatches("Ran 0 tests in ...s\n\nOK\n", doctest.ELLIPSIS))
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)
335 self.result.stopTestRun()
336 self.assertThat(self.getvalue(),
337 DocTestMatches("... in 0.001s\n...", doctest.ELLIPSIS))
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))
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))
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))
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)
366 self.result.stopTestRun()
367 self.assertThat(self.getvalue(),
368 DocTestMatches("""...======================================================================
369 ERROR: testtools.tests.test_testresult.Test.error
370 ----------------------------------------------------------------------
371 Text attachment: traceback
373 Traceback (most recent call last):
374 File "...testtools...runtest.py", line ..., in _run_user...
376 File "...testtools...testcase.py", line ..., in _run_test_method
378 File "...testtools...tests...test_testresult.py", line ..., in error
380 ZeroDivisionError: int... division or modulo by zero
382 ======================================================================
383 FAIL: testtools.tests.test_testresult.Test.failed
384 ----------------------------------------------------------------------
385 Text attachment: traceback
387 Traceback (most recent call last):
388 File "...testtools...runtest.py", line ..., in _run_user...
390 File "...testtools...testcase.py", line ..., in _run_test_method
392 File "...testtools...tests...test_testresult.py", line ..., in failed
396 ...""", doctest.ELLIPSIS))
399 class TestThreadSafeForwardingResult(TestWithFakeExceptions):
400 """Tests for `MultiTestResult`."""
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)
409 def test_nonforwarding_methods(self):
410 # startTest and stopTest are not forwarded because they need to be
412 self.result1.startTest(self)
413 self.result1.stopTest(self)
414 self.assertEqual([], self.target._events)
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)
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)
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),
443 ('addFailure', self, exc_info2),
446 ('addSkip', self, reason),
449 ('addSuccess', self),
451 ], self.target._events)
454 class TestExtendedToOriginalResultDecoratorBase(TestCase):
456 def make_26_result(self):
457 self.result = Python26TestResult()
458 self.make_converter()
460 def make_27_result(self):
461 self.result = Python27TestResult()
462 self.make_converter()
464 def make_converter(self):
465 self.converter = ExtendedToOriginalDecorator(self.result)
467 def make_extended_result(self):
468 self.result = ExtendedTestResult()
469 self.make_converter()
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)
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")
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.
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)
503 def check_outcome_details_to_nothing(self, outcome, expected=None):
504 """Call an outcome with a details dict to be swallowed."""
507 details = {'foo': 'bar'}
508 getattr(self.converter, outcome)(self, details=details)
509 self.assertEqual([(expected, self)], self.result._events)
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)
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.
524 getattr(self.converter, outcome)(self, err)
525 self.assertEqual([(expected, self, err)], self.result._events)
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.
534 getattr(self.converter, outcome)(self, err)
535 self.assertEqual([(expected, self)], self.result._events)
537 def check_outcome_nothing(self, outcome, expected=None):
538 """Check that calling a legacy outcome still works."""
541 getattr(self.converter, outcome)(self)
542 self.assertEqual([(expected, self)], self.result._events)
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)
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)
555 class TestExtendedToOriginalResultDecorator(
556 TestExtendedToOriginalResultDecoratorBase):
558 def test_progress_py26(self):
559 self.make_26_result()
560 self.converter.progress(1, 2)
562 def test_progress_py27(self):
563 self.make_27_result()
564 self.converter.progress(1, 2)
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)
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)
577 def test_startTest_py26(self):
578 self.make_26_result()
579 self.converter.startTest(self)
580 self.assertEqual([('startTest', self)], self.result._events)
582 def test_startTest_py27(self):
583 self.make_27_result()
584 self.converter.startTest(self)
585 self.assertEqual([('startTest', self)], self.result._events)
587 def test_startTest_pyextended(self):
588 self.make_extended_result()
589 self.converter.startTest(self)
590 self.assertEqual([('startTest', self)], self.result._events)
592 def test_startTestRun_py26(self):
593 self.make_26_result()
594 self.converter.startTestRun()
595 self.assertEqual([], self.result._events)
597 def test_startTestRun_py27(self):
598 self.make_27_result()
599 self.converter.startTestRun()
600 self.assertEqual([('startTestRun',)], self.result._events)
602 def test_startTestRun_pyextended(self):
603 self.make_extended_result()
604 self.converter.startTestRun()
605 self.assertEqual([('startTestRun',)], self.result._events)
607 def test_stopTest_py26(self):
608 self.make_26_result()
609 self.converter.stopTest(self)
610 self.assertEqual([('stopTest', self)], self.result._events)
612 def test_stopTest_py27(self):
613 self.make_27_result()
614 self.converter.stopTest(self)
615 self.assertEqual([('stopTest', self)], self.result._events)
617 def test_stopTest_pyextended(self):
618 self.make_extended_result()
619 self.converter.stopTest(self)
620 self.assertEqual([('stopTest', self)], self.result._events)
622 def test_stopTestRun_py26(self):
623 self.make_26_result()
624 self.converter.stopTestRun()
625 self.assertEqual([], self.result._events)
627 def test_stopTestRun_py27(self):
628 self.make_27_result()
629 self.converter.stopTestRun()
630 self.assertEqual([('stopTestRun',)], self.result._events)
632 def test_stopTestRun_pyextended(self):
633 self.make_extended_result()
634 self.converter.stopTestRun()
635 self.assertEqual([('stopTestRun',)], self.result._events)
637 def test_tags_py26(self):
638 self.make_26_result()
639 self.converter.tags(1, 2)
641 def test_tags_py27(self):
642 self.make_27_result()
643 self.converter.tags(1, 2)
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)
650 def test_time_py26(self):
651 self.make_26_result()
652 self.converter.time(1)
654 def test_time_py27(self):
655 self.make_27_result()
656 self.converter.time(1)
658 def test_time_pyextended(self):
659 self.make_extended_result()
660 self.converter.time(1)
661 self.assertEqual([('time', 1)], self.result._events)
664 class TestExtendedToOriginalAddError(TestExtendedToOriginalResultDecoratorBase):
668 def test_outcome_Original_py26(self):
669 self.make_26_result()
670 self.check_outcome_exc_info(self.outcome)
672 def test_outcome_Original_py27(self):
673 self.make_27_result()
674 self.check_outcome_exc_info(self.outcome)
676 def test_outcome_Original_pyextended(self):
677 self.make_extended_result()
678 self.check_outcome_exc_info(self.outcome)
680 def test_outcome_Extended_py26(self):
681 self.make_26_result()
682 self.check_outcome_details_to_exec_info(self.outcome)
684 def test_outcome_Extended_py27(self):
685 self.make_27_result()
686 self.check_outcome_details_to_exec_info(self.outcome)
688 def test_outcome_Extended_pyextended(self):
689 self.make_extended_result()
690 self.check_outcome_details(self.outcome)
692 def test_outcome__no_details(self):
693 self.make_extended_result()
694 self.assertRaises(ValueError,
695 getattr(self.converter, self.outcome), self)
698 class TestExtendedToOriginalAddFailure(
699 TestExtendedToOriginalAddError):
701 outcome = 'addFailure'
704 class TestExtendedToOriginalAddExpectedFailure(
705 TestExtendedToOriginalAddError):
707 outcome = 'addExpectedFailure'
709 def test_outcome_Original_py26(self):
710 self.make_26_result()
711 self.check_outcome_exc_info_to_nothing(self.outcome, 'addSuccess')
713 def test_outcome_Extended_py26(self):
714 self.make_26_result()
715 self.check_outcome_details_to_nothing(self.outcome, 'addSuccess')
719 class TestExtendedToOriginalAddSkip(
720 TestExtendedToOriginalResultDecoratorBase):
724 def test_outcome_Original_py26(self):
725 self.make_26_result()
726 self.check_outcome_string_nothing(self.outcome, 'addSuccess')
728 def test_outcome_Original_py27(self):
729 self.make_27_result()
730 self.check_outcome_string(self.outcome)
732 def test_outcome_Original_pyextended(self):
733 self.make_extended_result()
734 self.check_outcome_string(self.outcome)
736 def test_outcome_Extended_py26(self):
737 self.make_26_result()
738 self.check_outcome_string_nothing(self.outcome, 'addSuccess')
740 def test_outcome_Extended_py27(self):
741 self.make_27_result()
742 self.check_outcome_details_to_string(self.outcome)
744 def test_outcome_Extended_pyextended(self):
745 self.make_extended_result()
746 self.check_outcome_details(self.outcome)
748 def test_outcome__no_details(self):
749 self.make_extended_result()
750 self.assertRaises(ValueError,
751 getattr(self.converter, self.outcome), self)
754 class TestExtendedToOriginalAddSuccess(
755 TestExtendedToOriginalResultDecoratorBase):
757 outcome = 'addSuccess'
758 expected = 'addSuccess'
760 def test_outcome_Original_py26(self):
761 self.make_26_result()
762 self.check_outcome_nothing(self.outcome, self.expected)
764 def test_outcome_Original_py27(self):
765 self.make_27_result()
766 self.check_outcome_nothing(self.outcome)
768 def test_outcome_Original_pyextended(self):
769 self.make_extended_result()
770 self.check_outcome_nothing(self.outcome)
772 def test_outcome_Extended_py26(self):
773 self.make_26_result()
774 self.check_outcome_details_to_nothing(self.outcome, self.expected)
776 def test_outcome_Extended_py27(self):
777 self.make_27_result()
778 self.check_outcome_details_to_nothing(self.outcome)
780 def test_outcome_Extended_pyextended(self):
781 self.make_extended_result()
782 self.check_outcome_details(self.outcome)
785 class TestExtendedToOriginalAddUnexpectedSuccess(
786 TestExtendedToOriginalAddSuccess):
788 outcome = 'addUnexpectedSuccess'
791 class TestExtendedToOriginalResultOtherAttributes(
792 TestExtendedToOriginalResultDecoratorBase):
794 def test_other_attribute(self):
795 class OtherExtendedResult:
799 self.result = OtherExtendedResult()
800 self.make_converter()
801 self.assertEqual(1, self.converter.bar)
802 self.assertEqual(2, self.converter.foo())
806 from unittest import TestLoader
807 return TestLoader().loadTestsFromName(__name__)