summaryrefslogtreecommitdiff
path: root/lib/testtools/testtools/tests/test_testresult.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/testtools/testtools/tests/test_testresult.py')
-rw-r--r--lib/testtools/testtools/tests/test_testresult.py307
1 files changed, 220 insertions, 87 deletions
diff --git a/lib/testtools/testtools/tests/test_testresult.py b/lib/testtools/testtools/tests/test_testresult.py
index 57c3293c09..a241788bea 100644
--- a/lib/testtools/testtools/tests/test_testresult.py
+++ b/lib/testtools/testtools/tests/test_testresult.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2008 Jonathan M. Lange. See LICENSE for details.
+# Copyright (c) 2008-2011 testtools developers. See LICENSE for details.
"""Test TestResults and related things."""
@@ -22,7 +22,6 @@ from testtools import (
TextTestResult,
ThreadsafeForwardingResult,
testresult,
- try_imports,
)
from testtools.compat import (
_b,
@@ -30,24 +29,70 @@ from testtools.compat import (
_r,
_u,
str_is_unicode,
+ StringIO,
+ )
+from testtools.content import (
+ Content,
+ content_from_stream,
+ text_content,
)
-from testtools.content import Content
from testtools.content_type import ContentType, UTF8_TEXT
from testtools.matchers import (
DocTestMatches,
+ Equals,
MatchesException,
Raises,
)
from testtools.tests.helpers import (
+ an_exc_info,
+ FullStackRunTest,
LoggingResult,
+ run_with_stack_hidden,
+ )
+from testtools.testresult.doubles import (
Python26TestResult,
Python27TestResult,
ExtendedTestResult,
- an_exc_info
)
-from testtools.testresult.real import utc
+from testtools.testresult.real import (
+ _details_to_str,
+ utc,
+ )
+
+
+def make_erroring_test():
+ class Test(TestCase):
+ def error(self):
+ 1/0
+ return Test("error")
+
+
+def make_failing_test():
+ class Test(TestCase):
+ def failed(self):
+ self.fail("yo!")
+ return Test("failed")
+
+
+def make_unexpectedly_successful_test():
+ class Test(TestCase):
+ def succeeded(self):
+ self.expectFailure("yo!", lambda: None)
+ return Test("succeeded")
+
-StringIO = try_imports(['StringIO.StringIO', 'io.StringIO'])
+def make_test():
+ class Test(TestCase):
+ def test(self):
+ pass
+ return Test("test")
+
+
+def make_exception_info(exceptionFactory, *args, **kwargs):
+ try:
+ raise exceptionFactory(*args, **kwargs)
+ except:
+ return sys.exc_info()
class Python26Contract(object):
@@ -190,7 +235,7 @@ class FallbackContract(DetailsContract):
class StartTestRunContract(FallbackContract):
"""Defines the contract for testtools policy choices.
-
+
That is things which are not simply extensions to unittest but choices we
have made differently.
"""
@@ -222,24 +267,32 @@ class StartTestRunContract(FallbackContract):
class TestTestResultContract(TestCase, StartTestRunContract):
+ run_test_with = FullStackRunTest
+
def makeResult(self):
return TestResult()
class TestMultiTestResultContract(TestCase, StartTestRunContract):
+ run_test_with = FullStackRunTest
+
def makeResult(self):
return MultiTestResult(TestResult(), TestResult())
class TestTextTestResultContract(TestCase, StartTestRunContract):
+ run_test_with = FullStackRunTest
+
def makeResult(self):
return TextTestResult(StringIO())
class TestThreadSafeForwardingResultContract(TestCase, StartTestRunContract):
+ run_test_with = FullStackRunTest
+
def makeResult(self):
result_semaphore = threading.Semaphore(1)
target = TestResult()
@@ -277,7 +330,9 @@ class TestAdaptedPython27TestResultContract(TestCase, DetailsContract):
class TestTestResult(TestCase):
- """Tests for `TestResult`."""
+ """Tests for 'TestResult'."""
+
+ run_tests_with = FullStackRunTest
def makeResult(self):
"""Make an arbitrary result for testing."""
@@ -328,21 +383,45 @@ class TestTestResult(TestCase):
result.time(now)
self.assertEqual(now, result._now())
-
-class TestWithFakeExceptions(TestCase):
-
- def makeExceptionInfo(self, exceptionFactory, *args, **kwargs):
- try:
- raise exceptionFactory(*args, **kwargs)
- except:
- return sys.exc_info()
+ def test_traceback_formatting_without_stack_hidden(self):
+ # During the testtools test run, we show our levels of the stack,
+ # because we want to be able to use our test suite to debug our own
+ # code.
+ result = self.makeResult()
+ test = make_erroring_test()
+ test.run(result)
+ self.assertThat(
+ result.errors[0][1],
+ DocTestMatches(
+ 'Traceback (most recent call last):\n'
+ ' File "...testtools...runtest.py", line ..., in _run_user\n'
+ ' return fn(*args, **kwargs)\n'
+ ' File "...testtools...testcase.py", line ..., in _run_test_method\n'
+ ' return self._get_test_method()()\n'
+ ' File "...testtools...tests...test_testresult.py", line ..., in error\n'
+ ' 1/0\n'
+ 'ZeroDivisionError: ...\n',
+ doctest.ELLIPSIS | doctest.REPORT_UDIFF))
+
+ def test_traceback_formatting_with_stack_hidden(self):
+ result = self.makeResult()
+ test = make_erroring_test()
+ run_with_stack_hidden(True, test.run, result)
+ self.assertThat(
+ result.errors[0][1],
+ DocTestMatches(
+ 'Traceback (most recent call last):\n'
+ ' File "...testtools...tests...test_testresult.py", line ..., in error\n'
+ ' 1/0\n'
+ 'ZeroDivisionError: ...\n',
+ doctest.ELLIPSIS))
-class TestMultiTestResult(TestWithFakeExceptions):
- """Tests for `MultiTestResult`."""
+class TestMultiTestResult(TestCase):
+ """Tests for 'MultiTestResult'."""
def setUp(self):
- TestWithFakeExceptions.setUp(self)
+ super(TestMultiTestResult, self).setUp()
self.result1 = LoggingResult([])
self.result2 = LoggingResult([])
self.multiResult = MultiTestResult(self.result1, self.result2)
@@ -391,14 +470,14 @@ class TestMultiTestResult(TestWithFakeExceptions):
def test_addFailure(self):
# Calling `addFailure` on a `MultiTestResult` calls `addFailure` on
# all its `TestResult`s.
- exc_info = self.makeExceptionInfo(AssertionError, 'failure')
+ exc_info = make_exception_info(AssertionError, 'failure')
self.multiResult.addFailure(self, exc_info)
self.assertResultLogsEqual([('addFailure', self, exc_info)])
def test_addError(self):
# Calling `addError` on a `MultiTestResult` calls `addError` on all
# its `TestResult`s.
- exc_info = self.makeExceptionInfo(RuntimeError, 'error')
+ exc_info = make_exception_info(RuntimeError, 'error')
self.multiResult.addError(self, exc_info)
self.assertResultLogsEqual([('addError', self, exc_info)])
@@ -432,36 +511,12 @@ class TestMultiTestResult(TestWithFakeExceptions):
class TestTextTestResult(TestCase):
- """Tests for `TextTestResult`."""
+ """Tests for 'TextTestResult'."""
def setUp(self):
super(TestTextTestResult, self).setUp()
self.result = TextTestResult(StringIO())
- def make_erroring_test(self):
- class Test(TestCase):
- def error(self):
- 1/0
- return Test("error")
-
- def make_failing_test(self):
- class Test(TestCase):
- def failed(self):
- self.fail("yo!")
- return Test("failed")
-
- def make_unexpectedly_successful_test(self):
- class Test(TestCase):
- def succeeded(self):
- self.expectFailure("yo!", lambda: None)
- return Test("succeeded")
-
- def make_test(self):
- class Test(TestCase):
- def test(self):
- pass
- return Test("test")
-
def getvalue(self):
return self.result.stream.getvalue()
@@ -477,7 +532,7 @@ class TestTextTestResult(TestCase):
self.assertEqual("Tests running...\n", self.getvalue())
def test_stopTestRun_count_many(self):
- test = self.make_test()
+ test = make_test()
self.result.startTestRun()
self.result.startTest(test)
self.result.stopTest(test)
@@ -486,27 +541,27 @@ class TestTextTestResult(TestCase):
self.result.stream = StringIO()
self.result.stopTestRun()
self.assertThat(self.getvalue(),
- DocTestMatches("Ran 2 tests in ...s\n...", doctest.ELLIPSIS))
+ DocTestMatches("\nRan 2 tests in ...s\n...", doctest.ELLIPSIS))
def test_stopTestRun_count_single(self):
- test = self.make_test()
+ test = make_test()
self.result.startTestRun()
self.result.startTest(test)
self.result.stopTest(test)
self.reset_output()
self.result.stopTestRun()
self.assertThat(self.getvalue(),
- DocTestMatches("Ran 1 test in ...s\n\nOK\n", doctest.ELLIPSIS))
+ DocTestMatches("\nRan 1 test in ...s\nOK\n", doctest.ELLIPSIS))
def test_stopTestRun_count_zero(self):
self.result.startTestRun()
self.reset_output()
self.result.stopTestRun()
self.assertThat(self.getvalue(),
- DocTestMatches("Ran 0 tests in ...s\n\nOK\n", doctest.ELLIPSIS))
+ DocTestMatches("\nRan 0 tests in ...s\nOK\n", doctest.ELLIPSIS))
def test_stopTestRun_current_time(self):
- test = self.make_test()
+ test = make_test()
now = datetime.datetime.now(utc)
self.result.time(now)
self.result.startTestRun()
@@ -523,79 +578,67 @@ class TestTextTestResult(TestCase):
self.result.startTestRun()
self.result.stopTestRun()
self.assertThat(self.getvalue(),
- DocTestMatches("...\n\nOK\n", doctest.ELLIPSIS))
+ DocTestMatches("...\nOK\n", doctest.ELLIPSIS))
def test_stopTestRun_not_successful_failure(self):
- test = self.make_failing_test()
+ test = make_failing_test()
self.result.startTestRun()
test.run(self.result)
self.result.stopTestRun()
self.assertThat(self.getvalue(),
- DocTestMatches("...\n\nFAILED (failures=1)\n", doctest.ELLIPSIS))
+ DocTestMatches("...\nFAILED (failures=1)\n", doctest.ELLIPSIS))
def test_stopTestRun_not_successful_error(self):
- test = self.make_erroring_test()
+ test = make_erroring_test()
self.result.startTestRun()
test.run(self.result)
self.result.stopTestRun()
self.assertThat(self.getvalue(),
- DocTestMatches("...\n\nFAILED (failures=1)\n", doctest.ELLIPSIS))
+ DocTestMatches("...\nFAILED (failures=1)\n", doctest.ELLIPSIS))
def test_stopTestRun_not_successful_unexpected_success(self):
- test = self.make_unexpectedly_successful_test()
+ test = make_unexpectedly_successful_test()
self.result.startTestRun()
test.run(self.result)
self.result.stopTestRun()
self.assertThat(self.getvalue(),
- DocTestMatches("...\n\nFAILED (failures=1)\n", doctest.ELLIPSIS))
+ DocTestMatches("...\nFAILED (failures=1)\n", doctest.ELLIPSIS))
def test_stopTestRun_shows_details(self):
- self.result.startTestRun()
- self.make_erroring_test().run(self.result)
- self.make_unexpectedly_successful_test().run(self.result)
- self.make_failing_test().run(self.result)
- self.reset_output()
- self.result.stopTestRun()
+ def run_tests():
+ self.result.startTestRun()
+ make_erroring_test().run(self.result)
+ make_unexpectedly_successful_test().run(self.result)
+ make_failing_test().run(self.result)
+ self.reset_output()
+ self.result.stopTestRun()
+ run_with_stack_hidden(True, run_tests)
self.assertThat(self.getvalue(),
DocTestMatches("""...======================================================================
ERROR: testtools.tests.test_testresult.Test.error
----------------------------------------------------------------------
-Text attachment: traceback
-------------
Traceback (most recent call last):
- File "...testtools...runtest.py", line ..., in _run_user...
- return fn(*args, **kwargs)
- File "...testtools...testcase.py", line ..., in _run_test_method
- return self._get_test_method()()
File "...testtools...tests...test_testresult.py", line ..., in error
1/0
ZeroDivisionError:... divi... by zero...
-------------
======================================================================
FAIL: testtools.tests.test_testresult.Test.failed
----------------------------------------------------------------------
-Text attachment: traceback
-------------
Traceback (most recent call last):
- File "...testtools...runtest.py", line ..., in _run_user...
- return fn(*args, **kwargs)
- File "...testtools...testcase.py", line ..., in _run_test_method
- return self._get_test_method()()
File "...testtools...tests...test_testresult.py", line ..., in failed
self.fail("yo!")
AssertionError: yo!
-------------
======================================================================
UNEXPECTED SUCCESS: testtools.tests.test_testresult.Test.succeeded
----------------------------------------------------------------------
...""", doctest.ELLIPSIS | doctest.REPORT_NDIFF))
-class TestThreadSafeForwardingResult(TestWithFakeExceptions):
+class TestThreadSafeForwardingResult(TestCase):
"""Tests for `TestThreadSafeForwardingResult`."""
def setUp(self):
- TestWithFakeExceptions.setUp(self)
+ super(TestThreadSafeForwardingResult, self).setUp()
self.result_semaphore = threading.Semaphore(1)
self.target = LoggingResult([])
self.result1 = ThreadsafeForwardingResult(self.target,
@@ -624,14 +667,14 @@ class TestThreadSafeForwardingResult(TestWithFakeExceptions):
def test_forwarding_methods(self):
# error, failure, skip and success are forwarded in batches.
- exc_info1 = self.makeExceptionInfo(RuntimeError, 'error')
+ exc_info1 = make_exception_info(RuntimeError, 'error')
starttime1 = datetime.datetime.utcfromtimestamp(1.489)
endtime1 = datetime.datetime.utcfromtimestamp(51.476)
self.result1.time(starttime1)
self.result1.startTest(self)
self.result1.time(endtime1)
self.result1.addError(self, exc_info1)
- exc_info2 = self.makeExceptionInfo(AssertionError, 'failure')
+ exc_info2 = make_exception_info(AssertionError, 'failure')
starttime2 = datetime.datetime.utcfromtimestamp(2.489)
endtime2 = datetime.datetime.utcfromtimestamp(3.476)
self.result1.time(starttime2)
@@ -708,10 +751,19 @@ class TestExtendedToOriginalResultDecoratorBase(TestCase):
details = {'text 1': Content(ContentType('text', 'plain'), text1),
'text 2': Content(ContentType('text', 'strange'), text2),
'bin 1': Content(ContentType('application', 'binary'), bin1)}
- return (details, "Binary content: bin 1\n"
- "Text attachment: text 1\n------------\n1\n2\n"
- "------------\nText attachment: text 2\n------------\n"
- "3\n4\n------------\n")
+ return (details,
+ ("Binary content:\n"
+ " bin 1 (application/binary)\n"
+ "\n"
+ "text 1: {{{\n"
+ "1\n"
+ "2\n"
+ "}}}\n"
+ "\n"
+ "text 2: {{{\n"
+ "3\n"
+ "4\n"
+ "}}}\n"))
def check_outcome_details_to_exec_info(self, outcome, expected=None):
"""Call an outcome with a details dict to be made into exc_info."""
@@ -1369,6 +1421,87 @@ class TestNonAsciiResultsWithUnittest(TestNonAsciiResults):
return text.encode("utf-8")
+class TestDetailsToStr(TestCase):
+
+ def test_no_details(self):
+ string = _details_to_str({})
+ self.assertThat(string, Equals(''))
+
+ def test_binary_content(self):
+ content = content_from_stream(
+ StringIO('foo'), content_type=ContentType('image', 'jpeg'))
+ string = _details_to_str({'attachment': content})
+ self.assertThat(
+ string, Equals("""\
+Binary content:
+ attachment (image/jpeg)
+"""))
+
+ def test_single_line_content(self):
+ content = text_content('foo')
+ string = _details_to_str({'attachment': content})
+ self.assertThat(string, Equals('attachment: {{{foo}}}\n'))
+
+ def test_multi_line_text_content(self):
+ content = text_content('foo\nbar\nbaz')
+ string = _details_to_str({'attachment': content})
+ self.assertThat(string, Equals('attachment: {{{\nfoo\nbar\nbaz\n}}}\n'))
+
+ def test_special_text_content(self):
+ content = text_content('foo')
+ string = _details_to_str({'attachment': content}, special='attachment')
+ self.assertThat(string, Equals('foo\n'))
+
+ def test_multiple_text_content(self):
+ string = _details_to_str(
+ {'attachment': text_content('foo\nfoo'),
+ 'attachment-1': text_content('bar\nbar')})
+ self.assertThat(
+ string, Equals('attachment: {{{\n'
+ 'foo\n'
+ 'foo\n'
+ '}}}\n'
+ '\n'
+ 'attachment-1: {{{\n'
+ 'bar\n'
+ 'bar\n'
+ '}}}\n'))
+
+ def test_empty_attachment(self):
+ string = _details_to_str({'attachment': text_content('')})
+ self.assertThat(
+ string, Equals("""\
+Empty attachments:
+ attachment
+"""))
+
+ def test_lots_of_different_attachments(self):
+ jpg = lambda x: content_from_stream(
+ StringIO(x), ContentType('image', 'jpeg'))
+ attachments = {
+ 'attachment': text_content('foo'),
+ 'attachment-1': text_content('traceback'),
+ 'attachment-2': jpg('pic1'),
+ 'attachment-3': text_content('bar'),
+ 'attachment-4': text_content(''),
+ 'attachment-5': jpg('pic2'),
+ }
+ string = _details_to_str(attachments, special='attachment-1')
+ self.assertThat(
+ string, Equals("""\
+Binary content:
+ attachment-2 (image/jpeg)
+ attachment-5 (image/jpeg)
+Empty attachments:
+ attachment-4
+
+attachment: {{{foo}}}
+attachment-3: {{{bar}}}
+
+traceback
+"""))
+
+
def test_suite():
from unittest import TestLoader
return TestLoader().loadTestsFromName(__name__)