Previously, when gathering details caused by a setUp failure, a traceback occurred if the fixture used the newer _setUp(). This also had the side effect of not clearing up fixtures properly. Change-Id: I9d138e8d559e176867c6e3f4b89f784cf4d29f05 Fixes: https://bugs.launchpad.net/testtools/+bug/1469759
		
			
				
	
	
		
			182 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Copyright (c) 2010-2011 testtools developers. See LICENSE for details.
 | 
						|
 | 
						|
import unittest
 | 
						|
 | 
						|
from extras import try_import
 | 
						|
 | 
						|
from testtools import (
 | 
						|
    TestCase,
 | 
						|
    content,
 | 
						|
    content_type,
 | 
						|
    )
 | 
						|
from testtools.compat import _b, _u
 | 
						|
from testtools.matchers import (
 | 
						|
    Contains,
 | 
						|
    Equals,
 | 
						|
    )
 | 
						|
from testtools.testresult.doubles import (
 | 
						|
    ExtendedTestResult,
 | 
						|
    )
 | 
						|
 | 
						|
fixtures = try_import('fixtures')
 | 
						|
LoggingFixture = try_import('fixtures.tests.helpers.LoggingFixture')
 | 
						|
 | 
						|
class TestFixtureSupport(TestCase):
 | 
						|
 | 
						|
    def setUp(self):
 | 
						|
        super(TestFixtureSupport, self).setUp()
 | 
						|
        if fixtures is None or LoggingFixture is None:
 | 
						|
            self.skipTest("Need fixtures")
 | 
						|
 | 
						|
    def test_useFixture(self):
 | 
						|
        fixture = LoggingFixture()
 | 
						|
        class SimpleTest(TestCase):
 | 
						|
            def test_foo(self):
 | 
						|
                self.useFixture(fixture)
 | 
						|
        result = unittest.TestResult()
 | 
						|
        SimpleTest('test_foo').run(result)
 | 
						|
        self.assertTrue(result.wasSuccessful())
 | 
						|
        self.assertEqual(['setUp', 'cleanUp'], fixture.calls)
 | 
						|
 | 
						|
    def test_useFixture_cleanups_raise_caught(self):
 | 
						|
        calls = []
 | 
						|
        def raiser(ignored):
 | 
						|
            calls.append('called')
 | 
						|
            raise Exception('foo')
 | 
						|
        fixture = fixtures.FunctionFixture(lambda:None, raiser)
 | 
						|
        class SimpleTest(TestCase):
 | 
						|
            def test_foo(self):
 | 
						|
                self.useFixture(fixture)
 | 
						|
        result = unittest.TestResult()
 | 
						|
        SimpleTest('test_foo').run(result)
 | 
						|
        self.assertFalse(result.wasSuccessful())
 | 
						|
        self.assertEqual(['called'], calls)
 | 
						|
 | 
						|
    def test_useFixture_details_captured(self):
 | 
						|
        class DetailsFixture(fixtures.Fixture):
 | 
						|
            def setUp(self):
 | 
						|
                fixtures.Fixture.setUp(self)
 | 
						|
                self.addCleanup(delattr, self, 'content')
 | 
						|
                self.content = [_b('content available until cleanUp')]
 | 
						|
                self.addDetail('content',
 | 
						|
                    content.Content(content_type.UTF8_TEXT, self.get_content))
 | 
						|
            def get_content(self):
 | 
						|
                return self.content
 | 
						|
        fixture = DetailsFixture()
 | 
						|
        class SimpleTest(TestCase):
 | 
						|
            def test_foo(self):
 | 
						|
                self.useFixture(fixture)
 | 
						|
                # Add a colliding detail (both should show up)
 | 
						|
                self.addDetail('content',
 | 
						|
                    content.Content(content_type.UTF8_TEXT, lambda:[_b('foo')]))
 | 
						|
        result = ExtendedTestResult()
 | 
						|
        SimpleTest('test_foo').run(result)
 | 
						|
        self.assertEqual('addSuccess', result._events[-2][0])
 | 
						|
        details = result._events[-2][2]
 | 
						|
        self.assertEqual(['content', 'content-1'], sorted(details.keys()))
 | 
						|
        self.assertEqual('foo', details['content'].as_text())
 | 
						|
        self.assertEqual('content available until cleanUp',
 | 
						|
            details['content-1'].as_text())
 | 
						|
 | 
						|
    def test_useFixture_multiple_details_captured(self):
 | 
						|
        class DetailsFixture(fixtures.Fixture):
 | 
						|
            def setUp(self):
 | 
						|
                fixtures.Fixture.setUp(self)
 | 
						|
                self.addDetail('aaa', content.text_content("foo"))
 | 
						|
                self.addDetail('bbb', content.text_content("bar"))
 | 
						|
        fixture = DetailsFixture()
 | 
						|
        class SimpleTest(TestCase):
 | 
						|
            def test_foo(self):
 | 
						|
                self.useFixture(fixture)
 | 
						|
        result = ExtendedTestResult()
 | 
						|
        SimpleTest('test_foo').run(result)
 | 
						|
        self.assertEqual('addSuccess', result._events[-2][0])
 | 
						|
        details = result._events[-2][2]
 | 
						|
        self.assertEqual(['aaa', 'bbb'], sorted(details))
 | 
						|
        self.assertEqual(_u('foo'), details['aaa'].as_text())
 | 
						|
        self.assertEqual(_u('bar'), details['bbb'].as_text())
 | 
						|
 | 
						|
    def test_useFixture_details_captured_from_setUp(self):
 | 
						|
        # Details added during fixture set-up are gathered even if setUp()
 | 
						|
        # fails with an exception.
 | 
						|
        class BrokenFixture(fixtures.Fixture):
 | 
						|
            def setUp(self):
 | 
						|
                fixtures.Fixture.setUp(self)
 | 
						|
                self.addDetail('content', content.text_content("foobar"))
 | 
						|
                raise Exception()
 | 
						|
        fixture = BrokenFixture()
 | 
						|
        class SimpleTest(TestCase):
 | 
						|
            def test_foo(self):
 | 
						|
                self.useFixture(fixture)
 | 
						|
        result = ExtendedTestResult()
 | 
						|
        SimpleTest('test_foo').run(result)
 | 
						|
        self.assertEqual('addError', result._events[-2][0])
 | 
						|
        details = result._events[-2][2]
 | 
						|
        self.assertEqual(['content', 'traceback'], sorted(details))
 | 
						|
        self.assertEqual('foobar', ''.join(details['content'].iter_text()))
 | 
						|
 | 
						|
    def test_useFixture_details_captured_from__setUp(self):
 | 
						|
        # Newer Fixtures deprecates setUp() in favour of _setUp().
 | 
						|
        # https://bugs.launchpad.net/testtools/+bug/1469759 reports that
 | 
						|
        # this is broken when gathering details from a broken _setUp().
 | 
						|
        class BrokenFixture(fixtures.Fixture):
 | 
						|
            def _setUp(self):
 | 
						|
                fixtures.Fixture._setUp(self)
 | 
						|
                self.addDetail('broken', content.text_content("foobar"))
 | 
						|
                raise Exception("_setUp broke")
 | 
						|
        fixture = BrokenFixture()
 | 
						|
        class SimpleTest(TestCase):
 | 
						|
            def test_foo(self):
 | 
						|
                self.addDetail('foo_content', content.text_content("foo ok"))
 | 
						|
                self.useFixture(fixture)
 | 
						|
        result = ExtendedTestResult()
 | 
						|
        SimpleTest('test_foo').run(result)
 | 
						|
        self.assertEqual('addError', result._events[-2][0])
 | 
						|
        details = result._events[-2][2]
 | 
						|
        self.assertEqual(
 | 
						|
            ['broken', 'foo_content', 'traceback', 'traceback-1'],
 | 
						|
            sorted(details))
 | 
						|
        self.expectThat(
 | 
						|
            ''.join(details['broken'].iter_text()),
 | 
						|
            Equals('foobar'))
 | 
						|
        self.expectThat(
 | 
						|
            ''.join(details['foo_content'].iter_text()),
 | 
						|
            Equals('foo ok'))
 | 
						|
        self.expectThat(
 | 
						|
            ''.join(details['traceback'].iter_text()),
 | 
						|
            Contains('_setUp broke'))
 | 
						|
        self.expectThat(
 | 
						|
            ''.join(details['traceback-1'].iter_text()),
 | 
						|
            Contains('foobar'))
 | 
						|
 | 
						|
    def test_useFixture_original_exception_raised_if_gather_details_fails(self):
 | 
						|
        # In bug #1368440 it was reported that when a fixture fails setUp
 | 
						|
        # and gather_details errors on it, then the original exception that
 | 
						|
        # failed is not reported.
 | 
						|
        class BrokenFixture(fixtures.Fixture):
 | 
						|
            def getDetails(self):
 | 
						|
                raise AttributeError("getDetails broke")
 | 
						|
            def setUp(self):
 | 
						|
                fixtures.Fixture.setUp(self)
 | 
						|
                raise Exception("setUp broke")
 | 
						|
        fixture = BrokenFixture()
 | 
						|
        class SimpleTest(TestCase):
 | 
						|
            def test_foo(self):
 | 
						|
                self.useFixture(fixture)
 | 
						|
        result = ExtendedTestResult()
 | 
						|
        SimpleTest('test_foo').run(result)
 | 
						|
        self.assertEqual('addError', result._events[-2][0])
 | 
						|
        details = result._events[-2][2]
 | 
						|
        self.assertEqual(['traceback', 'traceback-1'], sorted(details))
 | 
						|
        self.assertThat(
 | 
						|
            ''.join(details['traceback'].iter_text()),
 | 
						|
            Contains('setUp broke'))
 | 
						|
        self.assertThat(
 | 
						|
            ''.join(details['traceback-1'].iter_text()),
 | 
						|
            Contains('getDetails broke'))
 | 
						|
 | 
						|
 | 
						|
def test_suite():
 | 
						|
    from unittest import TestLoader
 | 
						|
    return TestLoader().loadTestsFromName(__name__)
 |