testtools-dev team mailing list archive
-
testtools-dev team
-
Mailing list archive
-
Message #00230
[Merge] lp:~lifeless/testtools/fixtures into lp:testtools
Robert Collins has proposed merging lp:~lifeless/testtools/fixtures into lp:testtools.
Requested reviews:
testtools developers (testtools-dev)
useFixture. Woo.
--
https://code.launchpad.net/~lifeless/testtools/fixtures/+merge/39388
Your team testtools developers is requested to review the proposed merge of lp:~lifeless/testtools/fixtures into lp:testtools.
=== modified file 'MANUAL'
--- MANUAL 2010-10-17 16:34:55 +0000
+++ MANUAL 2010-10-26 16:56:50 +0000
@@ -116,6 +116,16 @@
``skipTest`` support, the ``skip`` name is now deprecated (but no warning
is emitted yet - some time in the future we may do so).
+TestCase.useFixture
+~~~~~~~~~~~~~~~~~~~
+
+``useFixture(fixture)`` calls setUp on the fixture, schedules a cleanup to
+clean it up, and schedules a cleanup to attach all details held by the
+fixture to the details dict of the test case. The fixture object should meet
+the ``fixtures.Fixture`` protocol (version 0.3.4 or newer). This is useful
+for moving code out of setUp and tearDown methods and into composable side
+classes.
+
New assertion methods
~~~~~~~~~~~~~~~~~~~~~
=== modified file 'NEWS'
--- NEWS 2010-10-25 22:10:37 +0000
+++ NEWS 2010-10-26 16:56:50 +0000
@@ -24,6 +24,9 @@
* addUnexpectedSuccess is translated to addFailure for test results that don't
know about addUnexpectedSuccess. (Jonathan Lange, #654474)
+* ``testools.TestCase.useFixture`` has been added to glue with fixtures nicely.
+ (Robert Collins)
+
0.9.7
~~~~~
=== modified file 'README'
--- README 2010-10-24 08:46:03 +0000
+++ README 2010-10-26 16:56:50 +0000
@@ -19,14 +19,21 @@
distributed under the same license as Python, see LICENSE for details.
-Dependencies
-------------
+Required Dependencies
+---------------------
* Python 2.4+ or 3.0+
+Optional Dependencies
+---------------------
+
If you would like to use our undocumented, unsupported Twisted support, then
you will need Twisted.
+If you want to use ``fixtures`` then you can either install fixtures (e.g. from
+https://launchpad.net/python-fixtures or http://pypi.python.org/pypi/fixtures)
+or alternatively just make sure your fixture objects obey the same protocol.
+
Bug reports and patches
-----------------------
=== modified file 'testtools/testcase.py'
--- testtools/testcase.py 2010-10-18 12:46:20 +0000
+++ testtools/testcase.py 2010-10-26 16:56:50 +0000
@@ -538,6 +538,35 @@
"""
return self._get_test_method()()
+ def useFixture(self, fixture):
+ """Use fixture in a test case.
+
+ The fixture will be setUp, and self.addCleanup(fixture.cleanUp) called.
+
+ :param fixture: The fixture to use.
+ :return: The fixture, after setting it up and scheduling a cleanup for
+ it.
+ """
+ fixture.setUp()
+ self.addCleanup(fixture.cleanUp)
+ self.addCleanup(self._gather_details, fixture.getDetails)
+ return fixture
+
+ def _gather_details(self, getDetails):
+ """Merge the details from getDetails() into self.getDetails()."""
+ details = getDetails()
+ my_details = self.getDetails()
+ for name, content_object in details.items():
+ new_name = name
+ disambiguator = itertools.count(1)
+ while new_name in my_details:
+ new_name = '%s-%d' % (name, advance_iterator(disambiguator))
+ name = new_name
+ content_bytes = list(content_object.iter_bytes())
+ content_callback = lambda:content_bytes
+ self.addDetail(name,
+ content.Content(content_object.content_type, content_callback))
+
def setUp(self):
unittest.TestCase.setUp(self)
self.__setup_called = True
=== modified file 'testtools/tests/test_testtools.py'
--- testtools/tests/test_testtools.py 2010-09-26 20:45:28 +0000
+++ testtools/tests/test_testtools.py 2010-10-26 16:56:50 +0000
@@ -6,6 +6,9 @@
import sys
import unittest
+import fixtures
+from fixtures.tests.helpers import LoggingFixture
+
from testtools import (
ErrorHolder,
MultipleExceptions,
@@ -13,6 +16,7 @@
TestCase,
clone_test_with_new_id,
content,
+ content_type,
skip,
skipIf,
skipUnless,
@@ -1122,6 +1126,59 @@
self.assertIs(marker, value)
+class TestFixtureSupport(TestCase):
+
+ 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 = ['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:['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', ''.join(details['content'].iter_text()))
+ self.assertEqual('content available until cleanUp',
+ ''.join(details['content-1'].iter_text()))
+
+
def test_suite():
from unittest import TestLoader
return TestLoader().loadTestsFromName(__name__)
Follow ups