Skip to content

Commit c7fefe1

Browse files
committed
README: Add comparison with fixtures
Signed-off-by: Stephen Finucane <stephen@that.guru>
1 parent 5708e6b commit c7fefe1

1 file changed

Lines changed: 58 additions & 6 deletions

File tree

README.rst

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ Usage
1111

1212
Here is a minimal example demonstrating how to use testresources in your
1313
project. It's not very useful - temporary directories are *not* the kind of
14-
resource that testresources are most useful for - but it does demonstrate some
15-
of the key concepts and classes, which we will discuss in more detail below.
16-
Firstly, we have our "resource manager":
14+
resource that testresources are most useful for and you would be better off
15+
using something like fixtures for this - but it does demonstrate some of the
16+
key concepts and classes, which we will discuss in more detail below. Firstly,
17+
we have our "resource manager":
1718

1819
.. code-block:: python
1920
@@ -204,12 +205,16 @@ See pydoc testresources.TestResourceManager for details.
204205

205206
Glue to adapt testresources to an existing resource-like class.
206207

208+
.. _fixtureresource:
209+
207210
``testresources.FixtureResource``
208211
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
209212

210-
Glue to adapt testresources to the simpler fixtures.Fixture API. Long
211-
term testresources is likely to consolidate on that simpler API as the
212-
recommended method of writing resources.
213+
Glue to adapt testresources to the simpler ``fixtures.Fixture`` API. Long term
214+
testresources is likely to consolidate on that simpler API as the recommended
215+
method of writing resources.
216+
217+
This is discussed in further detail in `testresources vs. fixtures`_.
213218

214219
``testresources.OptimisingTestSuite``
215220
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -264,6 +269,53 @@ see if it is safe to reuse.
264269
Finally, you can arrange for the returned resource to always call back to
265270
``TestResourceManager.dirtied`` on the first operation that mutates it.
266271

272+
testresources vs. fixtures
273+
--------------------------
274+
275+
The `fixtures <https://pypi.org/project/fixtures/>`_ library solves a similar
276+
problem: managing test dependencies that need to be set up and torn down.
277+
However, testresources and fixtures differ in the scope of the test
278+
dependencies they manage.
279+
280+
testresources is designed for resources that are expensive to create and can be
281+
safely shared across multiple tests. The ``OptimisingTestSuite`` reorders
282+
tests at the suite level so that tests sharing the same expensive resource run
283+
consecutively, minimising the total number of setup and teardown cycles. This
284+
makes sense when the cost of constructing the resource is meaningfully large
285+
relative to the cost of running the tests themselves. Examples of areas where
286+
testresources makes sense would be provisioning database backends that are
287+
shared across tests, or loading large, static test assets from disk.
288+
289+
By comparison, fixtures is designed for per-test setup and teardown. A fixture
290+
is created fresh (or at least reset) for each test, and tests interact with it
291+
via ``useFixture()``. fixtures is therefore far better suited for things like
292+
mock patches, temporary directories, fake loggers, environment variables, or
293+
fake HTTP sessions. In all these cases, the overhead of managing the resources
294+
is low enough that recreating them per test is perfectly acceptable.
295+
296+
Finally, there may be cases where you wish to use the framework provided by
297+
``fixtures.Fixture`` but avoid recreating it for every test in a module. To
298+
this end, the ``FixtureResource`` class is what you want. As discussed
299+
`previously <fixtureresource>`, this is a glue class that wraps any
300+
``fixtures.Fixture`` so it can participate in testresources' suite-level
301+
optimisation. If you already have a well-written fixture but want to avoid
302+
recreating it for every test in a module, wrapping it in a ``FixtureResource``
303+
and adding the ``load_tests`` hook is all that is needed. For example:
304+
305+
.. code-block:: python
306+
307+
# Defined once at module scope so that all tests share the same instance.
308+
MY_RESOURCE = testresources.FixtureResource(MyExpensiveFixture())
309+
310+
class MyTest(unittest.TestCase, testresources.ResourcedTestCase):
311+
resources = [('data', MY_RESOURCE)]
312+
313+
def test_something(self):
314+
self.data.some_attribute # provided by MyExpensiveFixture
315+
316+
def load_tests(loader, tests, pattern):
317+
return testresources.OptimisingTestSuite(tests)
318+
267319
FAQ
268320
---
269321

0 commit comments

Comments
 (0)