diff options
author | Robert Collins <robertc@robertcollins.net> | 2011-06-23 17:13:31 +1200 |
---|---|---|
committer | Robert Collins <robertc@robertcollins.net> | 2011-06-23 17:13:31 +1200 |
commit | 5ef29b108b18a2814944936b3e2862bb53f1b3c2 (patch) | |
tree | 3bc20e35b284c8586822377b85a866f52a39e901 | |
parent | b74f913548dc06e3a401c96d4230f87de68403e2 (diff) | |
parent | a6f79f5c8135e9b54fa963c23614d6be5404bb9e (diff) | |
download | fixtures-5ef29b108b18a2814944936b3e2862bb53f1b3c2.tar.gz |
* Details from child fixtures for both Fixture and TestWithFixtures no longer
quash same-named details if testtools 0.9.11 is available (for the
gather_details helper).
(Gavin Panella, #796253)
* Testtools 0.9.8 is now a minimum requirement.
(Gavin Panella)
-rw-r--r-- | NEWS | 8 | ||||
-rw-r--r-- | README | 8 | ||||
-rw-r--r-- | lib/fixtures/fixture.py | 28 | ||||
-rw-r--r-- | lib/fixtures/testcase.py | 19 | ||||
-rw-r--r-- | lib/fixtures/tests/test_fixture.py | 27 | ||||
-rw-r--r-- | lib/fixtures/tests/test_testcase.py | 54 |
6 files changed, 129 insertions, 15 deletions
@@ -8,6 +8,11 @@ IN DEVELOPMENT CHANGES: +* Details from child fixtures for both Fixture and TestWithFixtures no longer + quash same-named details if testtools 0.9.11 is available (for the + gather_details helper). + (Gavin Panella, #796253) + * New fixture ``PythonPathEntry`` which patches sys.path. (Robert Collins, #737503) @@ -15,6 +20,9 @@ CHANGES: test_cleanUp_raise_first_false_callscleanups_returns_exceptions. (Gavin Panella, #796249) +* Testtools 0.9.8 is now a minimum requirement. + (Gavin Panella) + 0.3.5 ~~~~~ @@ -26,6 +26,12 @@ Dependencies ============ * Python 2.4+ + This is the base language fixtures is written in and for. + +* testtools <https://launchpad.net/testtools> 0.9.8 or newer. + testtools provides helpful glue functions for the details API used to report + information about a fixture (whether its used in a testing or production + environment). For use in a unit test suite using the included glue, one of: @@ -35,8 +41,6 @@ For use in a unit test suite using the included glue, one of: * bzrlib.tests -* testtools <https://launchpad.net/testtools> - * Or any other test environment that supports TestCase.addCleanup. Writing your own glue code is easy, or you can simply use Fixtures directly diff --git a/lib/fixtures/fixture.py b/lib/fixtures/fixture.py index 933a9b2..c42bc44 100644 --- a/lib/fixtures/fixture.py +++ b/lib/fixtures/fixture.py @@ -22,11 +22,15 @@ __all__ = [ import sys -try: - from testtools import MultipleExceptions -except ImportError: - class MultipleExceptions(Exception): - """Report multiple exc_info tuples in self.args.""" +from testtools.helpers import try_import + +class MultipleExceptions(Exception): + """Report multiple exc_info tuples in self.args.""" + +MultipleExceptions = try_import( + "testtools.MultipleExceptions", MultipleExceptions) + +gather_details = try_import("testtools.testcase.gather_details") class Fixture(object): @@ -173,9 +177,17 @@ class Fixture(object): :return: The fixture, after setting it up and scheduling a cleanup for it. """ - fixture.setUp() - self.addCleanup(fixture.cleanUp) - return fixture + try: + fixture.setUp() + except: + if gather_details is not None: + gather_details(fixture, self) + raise + else: + self.addCleanup(fixture.cleanUp) + if gather_details is not None: + self.addCleanup(gather_details, fixture, self) + return fixture class FunctionFixture(Fixture): diff --git a/lib/fixtures/testcase.py b/lib/fixtures/testcase.py index 791a30b..38fc4ff 100644 --- a/lib/fixtures/testcase.py +++ b/lib/fixtures/testcase.py @@ -19,6 +19,8 @@ __all__ = [ import unittest +from fixtures.fixture import gather_details + class TestWithFixtures(unittest.TestCase): """A TestCase with a helper function to use fixtures. @@ -35,6 +37,17 @@ class TestWithFixtures(unittest.TestCase): :return: The fixture, after setting it up and scheduling a cleanup for it. """ - fixture.setUp() - self.addCleanup(fixture.cleanUp) - return fixture + use_details = ( + gather_details is not None and + getattr(self, "addDetail", None) is not None) + try: + fixture.setUp() + except: + if use_details: + gather_details(fixture, self) + raise + else: + self.addCleanup(fixture.cleanUp) + if use_details: + self.addCleanup(gather_details, fixture, self) + return fixture diff --git a/lib/fixtures/tests/test_fixture.py b/lib/fixtures/tests/test_fixture.py index 16659b6..28afe75 100644 --- a/lib/fixtures/tests/test_fixture.py +++ b/lib/fixtures/tests/test_fixture.py @@ -17,8 +17,11 @@ import sys import types import testtools +from testtools.content import text_content +from testtools.testcase import skipIf import fixtures +from fixtures.fixture import gather_details from fixtures.tests.helpers import LoggingFixture @@ -111,6 +114,30 @@ class TestFixture(testtools.TestCase): ['setUp-outer', 'setUp-inner', 'cleanUp-inner', 'cleanUp-outer'], parent.calls) + @skipIf(gather_details is None, "gather_details() is not available.") + def test_useFixture_details_captured_from_setUp(self): + # Details added during fixture set-up are gathered even if setUp() + # fails with an exception. + class SomethingBroke(Exception): pass + class BrokenFixture(fixtures.Fixture): + def setUp(self): + super(BrokenFixture, self).setUp() + self.addDetail('content', text_content("foobar")) + raise SomethingBroke() + broken_fixture = BrokenFixture() + class SimpleFixture(fixtures.Fixture): + def setUp(self): + super(SimpleFixture, self).setUp() + self.useFixture(broken_fixture) + simple_fixture = SimpleFixture() + self.assertRaises(SomethingBroke, simple_fixture.setUp) + self.assertEqual( + {"content": text_content("foobar")}, + broken_fixture.getDetails()) + self.assertEqual( + {"content": text_content("foobar")}, + simple_fixture.getDetails()) + def test_getDetails(self): fixture = fixtures.Fixture() with fixture: diff --git a/lib/fixtures/tests/test_testcase.py b/lib/fixtures/tests/test_testcase.py index aa9682d..3f186c5 100644 --- a/lib/fixtures/tests/test_testcase.py +++ b/lib/fixtures/tests/test_testcase.py @@ -15,8 +15,12 @@ import unittest import testtools +from testtools.content import text_content +from testtools.testcase import skipIf import fixtures +from fixtures import TestWithFixtures +from fixtures.fixture import gather_details from fixtures.tests.helpers import LoggingFixture @@ -24,7 +28,7 @@ class TestTestWithFixtures(unittest.TestCase): def test_useFixture(self): fixture = LoggingFixture() - class SimpleTest(testtools.TestCase, fixtures.TestWithFixtures): + class SimpleTest(testtools.TestCase, TestWithFixtures): def test_foo(self): self.useFixture(fixture) result = unittest.TestResult() @@ -38,10 +42,56 @@ class TestTestWithFixtures(unittest.TestCase): calls.append('called') raise Exception('foo') fixture = fixtures.FunctionFixture(lambda:None, raiser) - class SimpleTest(testtools.TestCase, fixtures.TestWithFixtures): + class SimpleTest(testtools.TestCase, TestWithFixtures): def test_foo(self): self.useFixture(fixture) result = unittest.TestResult() SimpleTest('test_foo').run(result) self.assertFalse(result.wasSuccessful()) self.assertEqual(['called'], calls) + + @skipIf(gather_details is None, "gather_details() is not available.") + def test_useFixture_details_captured_from_setUp(self): + # Details added during fixture set-up are gathered even if setUp() + # fails with an exception. + class SomethingBroke(Exception): pass + class BrokenFixture(fixtures.Fixture): + def setUp(self): + super(BrokenFixture, self).setUp() + self.addDetail('content', text_content("foobar")) + raise SomethingBroke() + broken_fixture = BrokenFixture() + class DetailedTestCase(TestWithFixtures, testtools.TestCase): + def setUp(self): + super(DetailedTestCase, self).setUp() + self.useFixture(broken_fixture) + def test(self): + pass + detailed_test_case = DetailedTestCase("test") + self.assertRaises(SomethingBroke, detailed_test_case.setUp) + self.assertEqual( + {"content": text_content("foobar")}, + broken_fixture.getDetails()) + self.assertEqual( + {"content": text_content("foobar")}, + detailed_test_case.getDetails()) + + @skipIf(gather_details is None, "gather_details() is not available.") + def test_useFixture_details_not_captured_from_setUp(self): + # Details added during fixture set-up are not gathered if the test + # case does not have the ability to accept those details. + class SomethingBroke(Exception): pass + class BrokenFixture(fixtures.Fixture): + def setUp(self): + super(BrokenFixture, self).setUp() + self.addDetail('content', text_content("foobar")) + raise SomethingBroke() + broken_fixture = BrokenFixture() + class NonDetailedTestCase(TestWithFixtures, unittest.TestCase): + def setUp(self): + super(NonDetailedTestCase, self).setUp() + self.useFixture(broken_fixture) + def test(self): + pass + non_detailed_test_case = NonDetailedTestCase("test") + self.assertRaises(SomethingBroke, non_detailed_test_case.setUp) |