summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Collins <robertc@robertcollins.net>2010-01-08 15:35:16 +1100
committerRobert Collins <robertc@robertcollins.net>2010-01-08 15:35:16 +1100
commit853d1f7b23b0de1acc4f1762b8b9645a7afaa0d9 (patch)
tree78a10b74720a1a2e73cc933008b706935f09fe20
parent25d8fb101adb930432ad232a15bce2baafdb6dfa (diff)
downloadtestresources-853d1f7b23b0de1acc4f1762b8b9645a7afaa0d9.tar.gz
Make public reusable functions for setting up and tearing down resources of a test.
-rw-r--r--NEWS4
-rw-r--r--lib/testresources/__init__.py80
-rw-r--r--lib/testresources/tests/test_resourced_test_case.py12
3 files changed, 66 insertions, 30 deletions
diff --git a/NEWS b/NEWS
index 37d91f9..3cff2a8 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,10 @@ BUG FIXES
API CHANGES
~~~~~~~~~~~
+* New public functions testresources.setUpResources and
+ testresources.tearDownResources for folk that cannot easily use
+ ResourcedTestCase. Fixes bug #504146.
+
INTERNALS
~~~~~~~~~
diff --git a/lib/testresources/__init__.py b/lib/testresources/__init__.py
index b9854a5..bed49b3 100644
--- a/lib/testresources/__init__.py
+++ b/lib/testresources/__init__.py
@@ -357,6 +357,13 @@ class TestResource(object):
class ResourcedTestCase(unittest.TestCase):
"""A TestCase parent or utility that enables cross-test resource usage.
+ ResourcedTestCase is a thin wrapper around the
+ testresources.setUpResources and testresources.tearDownResources helper
+ functions. It should be trivially reimplemented where a different base
+ class is neded, or you can use multiple inheritance and call into
+ ResourcedTestCase.setUpResources and ResourcedTestCase.tearDownResources
+ from your setUp and tearDown (or whatever cleanup idiom is used).
+
:ivar resources: A list of (name, resource) pairs, where 'resource' is a
subclass of `TestResource` and 'name' is the name of the attribute
that the resource should be stored on.
@@ -364,40 +371,61 @@ class ResourcedTestCase(unittest.TestCase):
resources = []
- def __get_result(self):
- # unittest hides the result. This forces us to look up the stack.
- # The result is passed to a run() or a __call__ method 4 or more frames
- # up: that method is what calls setUp and tearDown, and they call their
- # parent setUp etc. Its not guaranteed that the parameter to run will
- # be calls result as its not required to be a keyword parameter in
- # TestCase. However, in practice, this works.
- stack = inspect.stack()
- for frame in stack[3:]:
- if frame[3] in ('run', '__call__'):
- # Not all frames called 'run' will be unittest. It could be a
- # reactor in trial, for instance.
- result = frame[0].f_locals.get('result')
- if (result is not None and
- getattr(result, 'startTest', None) is not None):
- return result
-
def setUp(self):
unittest.TestCase.setUp(self)
self.setUpResources()
def setUpResources(self):
- """Set up any resources that this test needs."""
- result = self.__get_result()
- for resource in self.resources:
- setattr(self, resource[0], resource[1].getResource(result))
+ setUpResources(self, self.resources, _get_result())
def tearDown(self):
self.tearDownResources()
unittest.TestCase.tearDown(self)
def tearDownResources(self):
- """Tear down any resources that this test declares."""
- result = self.__get_result()
- for resource in self.resources:
- resource[1].finishedWith(getattr(self, resource[0]), result)
- delattr(self, resource[0])
+ tearDownResources(self, self.resources, _get_result())
+
+
+def setUpResources(test, resources, result):
+ """Set up resources for test.
+
+ :param test: The test to setup resources for.
+ :param resources: The resources to setup.
+ :param result: A result object for tracing resource activity.
+ """
+ for resource in resources:
+ setattr(test, resource[0], resource[1].getResource(result))
+
+
+def tearDownResources(test, resources, result):
+ """Tear down resources for test.
+
+ :param test: The test to tear down resources from.
+ :param resources: The resources to tear down.
+ :param result: A result object for tracing resource activity.
+ """
+ for resource in resources:
+ resource[1].finishedWith(getattr(test, resource[0]), result)
+ delattr(test, resource[0])
+
+
+def _get_result():
+ """Find a TestResult in the stack.
+
+ unittest hides the result. This forces us to look up the stack.
+ The result is passed to a run() or a __call__ method 4 or more frames
+ up: that method is what calls setUp and tearDown, and they call their
+ parent setUp etc. Its not guaranteed that the parameter to run will
+ be calls result as its not required to be a keyword parameter in
+ TestCase. However, in practice, this works.
+ """
+ stack = inspect.stack()
+ for frame in stack[2:]:
+ if frame[3] in ('run', '__call__'):
+ # Not all frames called 'run' will be unittest. It could be a
+ # reactor in trial, for instance.
+ result = frame[0].f_locals.get('result')
+ if (result is not None and
+ getattr(result, 'startTest', None) is not None):
+ return result
+
diff --git a/lib/testresources/tests/test_resourced_test_case.py b/lib/testresources/tests/test_resourced_test_case.py
index ee0a4ca..f613f39 100644
--- a/lib/testresources/tests/test_resourced_test_case.py
+++ b/lib/testresources/tests/test_resourced_test_case.py
@@ -67,7 +67,8 @@ class TestResourcedTestCase(testtools.TestCase):
def testSetUpResourcesSingle(self):
# setUpResources installs the resources listed in ResourcedTestCase.
self.resourced_case.resources = [("foo", self.resource_manager)]
- self.resourced_case.setUpResources()
+ testresources.setUpResources(self.resourced_case,
+ self.resourced_case.resources, None)
self.assertEqual(self.resource, self.resourced_case.foo)
def testSetUpResourcesMultiple(self):
@@ -75,7 +76,8 @@ class TestResourcedTestCase(testtools.TestCase):
self.resourced_case.resources = [
('foo', self.resource_manager),
('bar', MockResource('bar_resource'))]
- self.resourced_case.setUpResources()
+ testresources.setUpResources(self.resourced_case,
+ self.resourced_case.resources, None)
self.assertEqual(self.resource, self.resourced_case.foo)
self.assertEqual('bar_resource', self.resourced_case.bar)
@@ -86,14 +88,16 @@ class TestResourcedTestCase(testtools.TestCase):
# Give the 'foo' resource access to a 'bar' resource
self.resource_manager.resources.append(
('bar', MockResource('bar_resource')))
- self.resourced_case.setUpResources()
+ testresources.setUpResources(self.resourced_case,
+ self.resourced_case.resources, None)
self.assertEqual(resource, self.resourced_case.foo)
self.assertEqual('bar_resource', self.resourced_case.foo.bar)
def testSetUpUsesResource(self):
# setUpResources records a use of each declared resource.
self.resourced_case.resources = [("foo", self.resource_manager)]
- self.resourced_case.setUpResources()
+ testresources.setUpResources(self.resourced_case,
+ self.resourced_case.resources, None)
self.assertEqual(self.resource_manager._uses, 1)
def testTearDownResourcesDeletesResourceAttributes(self):