Run shared setup before pytest tests

Use a session fixture for reusable initialization, make its dependency scope explicit, and separate process-local reuse from coordination across parallel workers.

Best practices
Illustration of software components, data, and application workflows

Define a session-scoped fixture in a shared conftest.py. An unparametrized fixture is created when an applicable test first requests it, then reused within that test-process session. Add autouse=True when every test in its visibility scope should depend on it.

Define shared setup and teardown

# conftest.py in the test root
import pytest

@pytest.fixture(scope="session")
def global_setup():
    print("Initialize shared test resources")
    yield
    print("Release shared test resources")

A test can request it explicitly:

def test_something(global_setup):
    assert 1 + 1 == 2

For automatic use, change the decorator to @pytest.fixture(scope="session", autouse=True). This does not make initialization run before collection or at the instant pytest starts; fixtures belong to test execution. Dependencies determine the setup order.

Code after yield handles normal fixture teardown. If setup raises before reaching the yield, that section is not entered. Protect already-acquired resources with context managers, try/finally, or correctly registered finalizers.

Choose a scope that matches resource ownership

Scope Normal reuse boundary for an unparametrized fixture
function One test; the default.
class Tests in a class.
module Tests in one module.
package Tests within the fixture's package boundary.
session One pytest process session.

Parametrization can create multiple fixture instances within a scope. Visibility and lifetime are separate: a fixture in one test module is local to that module, while conftest.py fixtures are available to applicable tests in its directory tree without importing the file manually.

Reuse a connection while resetting test data

This small SQLite example belongs in conftest.py:

import sqlite3
import pytest

@pytest.fixture(scope="session")
def db_connection():
    conn = sqlite3.connect(":memory:")
    try:
        conn.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)")
        yield conn
    finally:
        conn.close()

@pytest.fixture(autouse=True)
def reset_table(db_connection):
    db_connection.execute("DELETE FROM users")
    db_connection.commit()

Each test starts with an empty table while the session reuses the connection. This is a teaching example, not a general transaction-isolation strategy for a live database. Schema changes or damaged transaction state may require stronger cleanup.

FAQ

Is a session fixture global across xdist workers?

No. Each worker that requests it has its own session and instance. A shared external resource needs coordination, such as a lock and reusable initialization result. The xdist documentation shows a FileLock pattern; a local file lock is insufficient if workers do not share that filesystem.

Should I use setUpClass instead?

unittest.TestCase.setUpClass runs per class. Pytest fixtures provide explicit dependencies, reusable scopes, and teardown. Existing unittest suites can retain their lifecycle; TestCase methods do not accept pytest fixture parameters in the same way as ordinary pytest functions.

Where should the fixture live?

Put it in the nearest common conftest.py for the tests that need it. Root-level autouse fixtures affect a wide set of tests, so use that scope intentionally.

References: pytest fixtures, pytest-xdist usage, pytest and unittest.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting