.. _xunitsetup: .. _setup: .. _`setup functions`: .. _`@pytest.setup`: ``@setup`` functions or: xunit on steroids ======================================================== .. versionadded:: 2.3 .. _`funcargs`: funcargs.html .. _`test parametrization`: funcargs.html#parametrizing-tests .. _`unittest plugin`: plugin/unittest.html .. _`xUnit`: http://en.wikipedia.org/wiki/XUnit Python, Java and many other languages support a so called xUnit_ style of resource setup. This typically involves the call of a ``setup`` ("fixture") method before running a test function and ``teardown`` after it has finished. Unlike :ref:`injected resources ` setup functions work indirectly by causing global side effects or setting test case attributes which test methods can then access. pytest originally introduced in 2005 a scope-specific model of detecting setup and teardown functions on a per-module, class or function basis. The Python unittest package and nose have subsequently incorporated them. This model remains supported by pytest as :ref:`old-style xunit`. Moreover, pytest-2.3 introduces a new ``pytest.setup()`` decorator to mark functions as setup functions which allow to implement everything you can do with the old-style and much more. Specifically setup functions: - can receive :ref:`resources through funcargs `, - fully interoperate with parametrized resources, - can be defined in a plugin or :ref:`conftest.py ` file and get called on a per-session, per-module, per-class or per-function basis, - can access the :ref:`request ` for which the setup is called, - can precisely control teardown by registering one or multiple teardown functions as soon as they have performed some actions which need undoing, eliminating the no need for a separate "teardown" decorator. - allow to separate different setup concerns even if they happen to work in the same scope All of these features are now demonstrated by little examples. .. _`new_setup`: .. _`@pytest.setup`: basic per-function setup ------------------------------- .. regendoc:wipe Suppose you want to have a clean directory with a single file entry for each test function in a module and have the test execute with this directory as current working dir:: # content of test_funcdir.py import pytest import os @pytest.setup() def mydir(tmpdir): tmpdir.join("myfile").write("example content") old = tmpdir.chdir() def test_function1(): assert os.path.exists("myfile") f = open("anotherfile", "w") f.write("") f.close() def test_function2(): assert os.path.exists("myfile") assert not os.path.exists("anotherfile") Our ``mydir`` setup function is executed on a per-function basis, the default scope used by the ``pytest.setup`` decorator. It accesses the ``tmpdir`` resource which provides a new empty directory path object. The ``test_function2`` here checks that it executes with a fresh directory and that it does not see the previously created ``anotherfile``. We can thus expect two passing tests:: $ py.test -v =========================== test session starts ============================ platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev7 -- /home/hpk/venv/1/bin/python cachedir: /home/hpk/tmp/doc-exec-410/.cache plugins: xdist, bugzilla, cache, oejskit, cli, pep8, cov collecting ... collected 2 items test_funcdir.py:9: test_function1 PASSED test_funcdir.py:15: test_function2 PASSED ========================= 2 passed in 0.26 seconds ========================= per-function setup, for every function of a project ------------------------------------------------------------ If you want to define a setup per-function but want to apply it to every function in your project you don't need to duplicate the setup-definition into each test module. Instead you can put it into a ``conftest.py`` file into the root of your project:: # content of conftest.py import pytest import os @pytest.setup() def cleandir(tmpdir): old = tmpdir.chdir() The ``cleandir`` setup function will be called for every test function below the directory tree where ``conftest.py`` resides. In this case it just uses the builtin ``tmpdir`` resource to change to the empty directory ahead of running a test. test modules accessing a global resource ------------------------------------------------------- .. note:: Relying on `global state is considered bad programming practise `_ but when you work with an application that relies on it you often have no choice. If you want test modules to access a global resource, you can stick the resource to the module globals in a per-module setup function. We use a :ref:`resource factory <@pytest.factory>` to create our global resource:: # content of conftest.py import pytest class GlobalResource: def __init__(self): pass @pytest.factory(scope="session") def globresource(): return GlobalResource() @pytest.setup(scope="module") def setresource(request, globresource): request.module.globresource = globresource Now any test module can access ``globresource`` as a module global:: # content of test_glob.py def test_1(): print ("test_1 %s" % globresource) def test_2(): print ("test_2 %s" % globresource) Let's run this module without output-capturing:: $ py.test -qs test_glob.py collecting ... collected 2 items .. 2 passed in 0.02 seconds test_1 test_2 The two tests see the same global ``globresource`` object. Parametrizing the global resource +++++++++++++++++++++++++++++++++++++++++++++++++ We extend the previous example and add parametrization to the globresource factory and also add a finalizer:: # content of conftest.py import pytest class GlobalResource: def __init__(self, param): self.param = param @pytest.factory(scope="session", params=[1,2]) def globresource(request): g = GlobalResource(request.param) def fin(): print "finalizing", g request.addfinalizer(fin) return g @pytest.setup(scope="module") def setresource(request, globresource): request.module.globresource = globresource And then re-run our test module:: $ py.test -qs test_glob.py collecting ... collected 4 items .... 4 passed in 0.02 seconds test_1 test_2 finalizing test_1 test_2 finalizing We are now running the two tests twice with two different global resource instances. Note that the tests are ordered such that only one instance is active at any given time: the finalizer of the first globresource instance is called before the second instance is created and sent to the setup functions.