Skip to main content
v2026.11,858 entries · CC-BY 4.0

Pytest Fixtures: Scopes, Yield Teardown and conftest.py

Define, share and clean up pytest fixtures in research code: scopes, yield teardown, tmp_path, conftest.py and params, per the pytest docs.

Written and maintained by CASRAI Editorial Board

Last updated

A pytest fixture is a function, marked with @pytest.fixture, that supplies a test with the data or resources it needs; a test uses it by naming it as an argument. This guide is for researchers who already have a first test running and now need shared setup (input data, temporary files, connections) and reliable cleanup. It follows the current pytest documentation, read on 2026-11-07.

What fixtures are used for in research code

The pytest documentation states that test functions request the fixtures they require by declaring them as arguments. In research code this replaces copy-pasted setup at the top of every test: the small input table, the output directory, the opened connection. Each test states what it needs in its signature, and pytest builds it. For the basics of writing a first test and the vocabulary around test fixtures, see What Is Unit Testing? Examples in Python and R; for measuring how much of your code the tests exercise, see Codecov for research code. Tests of this kind support computational reproducibility because they make the conditions of each check explicit.

Install or access

Install pytest following the official documentation, ideally inside a virtual environment:

python3 -m venv .venv
source .venv/bin/activate   # on Windows: .venvScriptsactivate
pip install -U pytest
pytest --version

The same page also shows uv add --dev pytest for projects managed with uv (prefix later commands with uv run). Running pytest with no arguments collects files matching test_*.py or *_test.py in the current directory and its subdirectories.

Step by step: define, request, share and tear down a fixture

1. Define a fixture and request it

Decorate a function with @pytest.fixture, then list its name as a parameter of any test that needs it. The numbers below are illustrative toy data.

import pytest

@pytest.fixture
def measurements():
    return [2.0, 4.0, 6.0]

def test_mean(measurements):
    assert sum(measurements) / len(measurements) == 4.0

2. Use the built-in tmp_path fixture for files

pytest ships a tmp_path fixture: a temporary directory unique to each test function, provided as a pathlib.Path. It suits analysis code that writes output files, because nothing is written into your project folder.

CONTENT = "content"

def test_create_file(tmp_path):
    d = tmp_path / "sub"
    d.mkdir()
    p = d / "hello.txt"
    p.write_text(CONTENT, encoding="utf-8")
    assert p.read_text(encoding="utf-8") == CONTENT

3. Clean up with yield

Use yield instead of return; code after the yield runs as teardown once the test finishes. When several fixtures are active, teardown runs in the reverse order of setup.

import smtplib
import pytest

@pytest.fixture(scope="module")
def smtp_connection():
    conn = smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
    yield conn
    conn.close()

The pattern is the same for any resource you open and must close, such as a database handle or an instrument connection.

4. Choose a scope

By default a fixture is created for each test function. Set scope to reuse an expensive setup across more tests, as in @pytest.fixture(scope="module"). The documented values are:

Scope value Meaning
function Default; one fixture instance per test function
class Shared within a test class
module Shared within a test module (file)
package Shared within a package
session Shared across the whole test session

5. Share fixtures with conftest.py

Fixtures defined in a conftest.py file can be used by tests in that directory without any import. Put project-wide fixtures there rather than copying them between test files.

6. Autouse and parametrized fixtures

With autouse=True, every test automatically requests the fixture, which suits setup that all tests need. With params, as in @pytest.fixture(scope="module", params=[...]), the current value is available as request.param and every dependent test runs once per value. That is a compact way to run the same check against several input values.

Output and how to read it

To see which fixtures are available, run pytest --fixtures. It lists the built-in fixtures and your own; fixtures whose names start with an underscore are hidden unless you add -v.

For tmp_path, pytest keeps the last 3 temporary directories by default (controlled by the tmp_path_retention_count and tmp_path_retention_policy settings), laid out as {temproot}/pytest-of-{user}/pytest-{num}/{testname}/. This lets you inspect files from a recent failing run. If you pass --basetemp=mydir, that directory is cleared blindly before each run, so never point it at a folder holding data you want to keep.

Free alternatives

pytest is itself free, open-source software. These other free Python test tools cover similar ground, but they do not use pytest’s fixture-by-argument model.

Tool What it is Setup and teardown approach Official docs
unittest Python’s built-in unit testing framework, part of the standard library setUp()/tearDown() run around each test method; setUpClass()/tearDownClass() run once per class; addCleanup() registers cleanup functions that run in reverse order unittest documentation
nose2 A test runner that extends unittest Builds on unittest’s fixtures and adds features such as the params decorator for running one test function with several values nose2 documentation

unittest needs no installation, which can matter on locked-down institutional machines.

Troubleshooting

  • A test cannot find a fixture. Run pytest --fixtures to confirm pytest sees it; shared fixtures belong in a conftest.py in the tests’ directory.
  • Cleanup code never runs. Teardown belongs after a yield; code placed after a return is never reached.
  • Expensive setup repeats for every test. The default scope is function; widen it with scope="module" or scope="session", remembering that tests then share that fixture instance.
  • Files from an earlier run are missing. Only the last 3 tmp_path directories are kept by default; adjust the retention settings if you need more.

FAQ

What is a pytest fixture?

A function decorated with @pytest.fixture that provides setup (and optionally teardown) to tests, which request it by listing its name as an argument.

How do I run teardown code after a test?

Write the fixture with yield instead of return and put the cleanup after the yield.

Where do shared fixtures go?

In conftest.py; tests in that directory can use them without importing.

How do I run one test with several input values?

Give the fixture a params list and read request.param; dependent tests run once per value.

Sources

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about Pytest Fixtures: Scopes, Yield Teardown and conftest.py

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →