[py-dev] using funcargs for setup/teardown

holger krekel holger at merlinux.eu
Fri Nov 6 12:34:51 CET 2009


Hi Frederik,

On Fri, Nov 06, 2009 at 10:36 +0000, Frederik Dohr wrote:
> >> http://gist.github.com/214495
> > 
> > not sure i see the need for funcargs with this example - 
> > why don't you use the "traditional" setup_module/teardown_module
> 
> I agree that it seems like overkill. (That's in part intentional though,
> due to it being a learning experience.)
> Yet I liked the idea of having a decorator for expressiveness/salience.
> 
> Also, I was under the impression that {setup,teardown}_{module,class}
> were deprecated (cf. Philippe's message), with funcargs generally being 
> the preferred option.

I actually considered deprecation but refrained from it. 

> Since I need setup and teardown for each individual test function,
> setup_module doesn't help me much - which leaves me with grouping tests
> into a class. I'm not entirely happy with that though, because it seems 
> a little boilerplatey and potentially makes for weird grouping of tests.
> 
> This led me to the option of a decorator wrapping the respective test 
> function in a "try: test(); finally: teardown()" - which worked fine, 
> but seemed to obscure the traceback on failures.

I see. 

> For my main project, I've realized that I don't actually need teardown.
> Instead, I use a function call (could perhaps become a decorator) at the
> _beginning_ of each test which resets the environment (e.g. erasing the
> data store). This has the added benefit of leaving inspectable leftovers
> after the last test (handy with py.test -x).
> I realize this tabula rasa approach might not be suitable for all
> projects though.

In any case it's fine to implement custom testing schemes.  For 
that matter you could automate invocation of a module-level 
"reset_test_environment" by writing down something like this:

    #./conftest.py  # basically a local project-specific plugin
    import py
    def pytest_runtest_setup(item): 
        if not isinstance(item, py.test.collect.Function):
            return # there are js/doc/other tests 
        modnode = item.getparent(py.test.collect.Module)
        module = modnode.obj # all python collect nodes have 'obj' 
        reset = hasattr('module', 'reset_test_environment', None)
        if reset is not None:
            reset(...) # pass custom parameters 

You can also pick up per-function parameters which you can 
set with with a decorator or maybe re-using the improved 
py.test.mark decorator which already works nicely with Python3.

HTH,

holger



More information about the Pytest-dev mailing list