How to run a method before all tests in all classes?

Solution 1:

Using session fixture as suggested by hpk42 is great solution for many cases, but fixture will run only after all tests are collected.

Here are two more solutions:

conftest hooks

Write a pytest_configure or pytest_sessionstart hook in your conftest.py file:

# content of conftest.py


def pytest_configure(config):
    """
    Allows plugins and conftest files to perform initial configuration.
    This hook is called for every plugin and initial conftest
    file after command line options have been parsed.
    """


def pytest_sessionstart(session):
    """
    Called after the Session object has been created and
    before performing collection and entering the run test loop.
    """


def pytest_sessionfinish(session, exitstatus):
    """
    Called after whole test run finished, right before
    returning the exit status to the system.
    """


def pytest_unconfigure(config):
    """
    called before test process is exited.
    """

pytest plugin

Create a pytest plugin with pytest_configure and pytest_unconfigure hooks.
Enable your plugin in conftest.py:

# content of conftest.py

pytest_plugins = [
    'plugins.example_plugin',
]


# content of plugins/example_plugin.py
def pytest_configure(config):
    pass


def pytest_unconfigure(config):
    pass

Solution 2:

You might want to use a session-scoped "autouse" fixture:

# content of conftest.py or a tests file (e.g. in your tests or root directory)

@pytest.fixture(scope="session", autouse=True)
def do_something(request):
    # prepare something ahead of all tests
    request.addfinalizer(finalizer_function)

This will run ahead of all tests. The finalizer will be called after the last test finished.

Solution 3:

Starting from version 2.10 there is a cleaner way to tear down the fixture as well as defining its scope. So you may use this syntax:

@pytest.fixture(scope="module", autouse=True)
def my_fixture():
    print ('INITIALIZATION')
    yield param
    print ('TEAR DOWN')

The autouse parameter: From documentation:

Here is how autouse fixtures work in other scopes:

  • autouse fixtures obey the scope= keyword-argument: if an autouse fixture has scope='session' it will only be run once, no matter where it is defined. scope='class' means it will be run once per class, etc.

  • if an autouse fixture is defined in a test module, all its test functions automatically use it.

  • if an autouse fixture is defined in a conftest.py file then all tests in all test modules below its directory will invoke the fixture.

    ...

The "request" parameter: Note that the "request" parameter is not necessary for your purpose although you might want to use it for other purposes. From documentation:

"Fixture function can accept the request object to introspect the “requesting” test function, class or module context.."