summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Collins <robertc@robertcollins.net>2011-06-23 17:13:31 +1200
committerRobert Collins <robertc@robertcollins.net>2011-06-23 17:13:31 +1200
commit5ef29b108b18a2814944936b3e2862bb53f1b3c2 (patch)
tree3bc20e35b284c8586822377b85a866f52a39e901
parentb74f913548dc06e3a401c96d4230f87de68403e2 (diff)
parenta6f79f5c8135e9b54fa963c23614d6be5404bb9e (diff)
downloadfixtures-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--NEWS8
-rw-r--r--README8
-rw-r--r--lib/fixtures/fixture.py28
-rw-r--r--lib/fixtures/testcase.py19
-rw-r--r--lib/fixtures/tests/test_fixture.py27
-rw-r--r--lib/fixtures/tests/test_testcase.py54
6 files changed, 129 insertions, 15 deletions
diff --git a/NEWS b/NEWS
index f46ce31..82f5d09 100644
--- a/NEWS
+++ b/NEWS
@@ -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
~~~~~
diff --git a/README b/README
index d2297a4..00b7327 100644
--- a/README
+++ b/README
@@ -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)