* `testools.TestCase.useFixture` has been added to glue with fixtures nicely.

(Robert Collins)
This commit is contained in:
Robert Collins
2010-10-27 05:52:16 +13:00
parent 295de056dc
commit ec9a05e4df
5 changed files with 108 additions and 2 deletions

10
MANUAL
View File

@@ -116,6 +116,16 @@ instead. ``skipTest`` was previously known as ``skip`` but as Python 2.7 adds
``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
~~~~~~~~~~~~~~~~~~~~~

3
NEWS
View File

@@ -24,6 +24,9 @@ Improvements
* 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
~~~~~

11
README
View File

@@ -19,14 +19,21 @@ is copyright Steve Purcell and the Python Software Foundation, it is
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
-----------------------

View File

@@ -538,6 +538,35 @@ class TestCase(unittest.TestCase):
"""
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

View File

@@ -6,6 +6,9 @@ from pprint import pformat
import sys
import unittest
import fixtures
from fixtures.tests.helpers import LoggingFixture
from testtools import (
ErrorHolder,
MultipleExceptions,
@@ -13,6 +16,7 @@ from testtools import (
TestCase,
clone_test_with_new_id,
content,
content_type,
skip,
skipIf,
skipUnless,
@@ -1122,6 +1126,59 @@ class TestPatchSupport(TestCase):
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__)