Update: Do read this entry, but I’ve written an update.
At The Health Agency we’re currently
switching to z3c.testsetup for
our test setup needs. The nice thing is that you only need one test .py file
that is found by your testrunner (I suggest tests/test_setup.py
) with the
following content:
import z3c.testsetup
test_suite = z3c.testsetup.register_all_tests('your.package.name')
No more manual building of test suites with DocTestCases and so. Just add
:doctest:
to every README or .txt or docstring-in-your.py like this:
.. :doctest:
>>> print 4
4
For testing our libraries, simple python-level doctests are often enough.
From time to time you need to call grokcore.component.grok('my.package')
but that’s about it. The base package for our grok sites needs a more
elaborate setup. And preferably a setup that is reusable in the grok sites
that use it.
Solution for more elaborate test setups: test layers. Zope.testing provides a layer mechanism. It took me some time to understand their use, but I think I’ve got it:
You can tie a test to a layer. All tests that “are on the same layer” are run in one group.
The layer can do setup before and after the layer’s tests are run. This means a layer is useful for setting up your zodb; an test sql database; some zcml setup.
The layer can also do extra layer-specific setup/teardown for every
individual test inside it. A layer that provides a zodb can thus arrange
for a transaction.abort()
to be done after every single test: test
isolation.
After an all-important from zope.app.testing.functional import
FunctionalTestSetup
, what my layer does is:
In the setUp(), instantiate FunctionalTestSetup with our own ftesting.zcml.
In the setUp(), grok a fixtures.py
with a test site object, some test
user folders, test adapters and so. This makes those grokked components
available to every test on this layer.
testSetUp() is the setup method that is called for every individual test. It calls FunctionalTestSetup’s setup that gives us a fresh clean ZODB. And it sets up a test grok site (of our own design) in the ZODB’s root.
On both levels there’s the corresponding tear down method.
Using layers is easy with z3c.testsetup: add a :layer: my.package.layer
.
One z3c.testsetup gotcha: it internally creates testcases, so it is hard to
pass in globals to the testcase (unless you do it in one go for all the tests
in the entire package, which wasn’t appropriate). The solution: call a setup
method by adding :setup: my.package.globsetup
to your doctest.
globsetup(test)
can append to the test.globs
dictionary. I found it a
bit dirty at first, but after using it for a while it smells OK. You set the
globs explicitly in those doctests where you need it. In every doctest, it is
clear which extra setup methods are called and thus it is easy to look up that
method to see which globals are available.
An alternative to this setup call is of course to do an from
my.package.globs import *
or something like that. Which seems a bit
cleaner. Time for some experimentation. Oh, if someone knows how to set the
globs from within a layer: please mail me.
Comment by Jasper: grok < 1.0a4 contain z3c.testsetup 0.2.1, so make sure you pin it to a more recent release like 0.4.
My name is Reinout van Rees and I work a lot with Python (programming language) and Django (website framework). I live in The Netherlands and I'm happily married to Annie van Rees-Kooiman.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):