* `testools.TestCase.useFixture` has been added to glue with fixtures nicely.
(Robert Collins)
This commit is contained in:
10
MANUAL
10
MANUAL
@@ -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
|
``skipTest`` support, the ``skip`` name is now deprecated (but no warning
|
||||||
is emitted yet - some time in the future we may do so).
|
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
|
New assertion methods
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|||||||
3
NEWS
3
NEWS
@@ -24,6 +24,9 @@ Improvements
|
|||||||
* addUnexpectedSuccess is translated to addFailure for test results that don't
|
* addUnexpectedSuccess is translated to addFailure for test results that don't
|
||||||
know about addUnexpectedSuccess. (Jonathan Lange, #654474)
|
know about addUnexpectedSuccess. (Jonathan Lange, #654474)
|
||||||
|
|
||||||
|
* ``testools.TestCase.useFixture`` has been added to glue with fixtures nicely.
|
||||||
|
(Robert Collins)
|
||||||
|
|
||||||
* Update documentation to say how to use testtools.run() on Python 2.4.
|
* Update documentation to say how to use testtools.run() on Python 2.4.
|
||||||
(Jonathan Lange, #501174)
|
(Jonathan Lange, #501174)
|
||||||
|
|
||||||
|
|||||||
11
README
11
README
@@ -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.
|
distributed under the same license as Python, see LICENSE for details.
|
||||||
|
|
||||||
|
|
||||||
Dependencies
|
Required Dependencies
|
||||||
------------
|
---------------------
|
||||||
|
|
||||||
* Python 2.4+ or 3.0+
|
* Python 2.4+ or 3.0+
|
||||||
|
|
||||||
|
Optional Dependencies
|
||||||
|
---------------------
|
||||||
|
|
||||||
If you would like to use our undocumented, unsupported Twisted support, then
|
If you would like to use our undocumented, unsupported Twisted support, then
|
||||||
you will need Twisted.
|
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
|
Bug reports and patches
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|||||||
@@ -538,6 +538,35 @@ class TestCase(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
return self._get_test_method()()
|
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):
|
def setUp(self):
|
||||||
unittest.TestCase.setUp(self)
|
unittest.TestCase.setUp(self)
|
||||||
self.__setup_called = True
|
self.__setup_called = True
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ from pprint import pformat
|
|||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
import fixtures
|
||||||
|
from fixtures.tests.helpers import LoggingFixture
|
||||||
|
|
||||||
from testtools import (
|
from testtools import (
|
||||||
ErrorHolder,
|
ErrorHolder,
|
||||||
MultipleExceptions,
|
MultipleExceptions,
|
||||||
@@ -13,6 +16,7 @@ from testtools import (
|
|||||||
TestCase,
|
TestCase,
|
||||||
clone_test_with_new_id,
|
clone_test_with_new_id,
|
||||||
content,
|
content,
|
||||||
|
content_type,
|
||||||
skip,
|
skip,
|
||||||
skipIf,
|
skipIf,
|
||||||
skipUnless,
|
skipUnless,
|
||||||
@@ -1122,6 +1126,59 @@ class TestPatchSupport(TestCase):
|
|||||||
self.assertIs(marker, value)
|
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():
|
def test_suite():
|
||||||
from unittest import TestLoader
|
from unittest import TestLoader
|
||||||
return TestLoader().loadTestsFromName(__name__)
|
return TestLoader().loadTestsFromName(__name__)
|
||||||
|
|||||||
Reference in New Issue
Block a user