pytest-dev/pytest · error · ValueError

class fixtures not supported (maybe in the future)

Error message

class fixtures not supported (maybe in the future)

What it means

FixtureFunctionDefinition.__call__ (fixtures.py:1428) rejects applying @pytest.fixture to a class. pytest fixtures must be functions; class-based fixtures are explicitly unsupported and the message notes 'maybe in the future'. This is a hard ValueError raised at decoration time, before any collection.

Solutions

  1. Convert the class into a fixture function returning an instance, or a factory fixture returning the class.
  2. If you need parametrized setup, use a factory fixture: def make_thing(): return Thing.
  3. Move the decorator to a method/function inside the class if a function was intended.

Example fix

// before
@pytest.fixture
class DbHelper:
    ...
// after
@pytest.fixture
def db_helper():
    return DbHelper()
Defensive patterns

Strategy: type-guard

Validate before calling

import inspect, functools
def fixture_or_factory(obj):
    assert not inspect.isclass(obj), '@pytest.fixture cannot decorate a class; pass a function'
    return obj
# usage: @functools.wraps ... ensure target is a function before decorating

Type guard

import inspect
def is_fixture_target_ok(fn) -> bool:
    return inspect.isfunction(fn) or inspect.ismethod(fn)

Prevention

When it happens

Trigger: Writing @pytest.fixture above a 'class Foo:' definition; attempting to use a class as a fixture (a pattern familiar from unittest setUpClass or dependency-injection frameworks).

Common situations: Migrating from a DI framework that uses classes; misunderstanding pytest's fixture model; accidentally stacking @pytest.fixture on a class helper instead of the function inside it.

Related errors


AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11). Data as JSON: /api/errors/d080482d14e51f65. Report an issue: GitHub.

Appendix: source

Thrown at src/_pytest/fixtures.py:1427


@final
@dataclasses.dataclass(frozen=True)
class FixtureFunctionMarker:
    scope: ScopeName | Callable[[str, Config], ScopeName]
    params: tuple[object, ...] | None
    autouse: bool = False
    ids: tuple[object | None, ...] | Callable[[Any], object | None] | None = None
    name: str | None = None

    _ispytest: dataclasses.InitVar[bool] = False

    def __post_init__(self, _ispytest: bool) -> None:
        check_ispytest(_ispytest)

    def __call__(self, function: FixtureFunction) -> FixtureFunctionDefinition:
        if inspect.isclass(function):
            raise ValueError("class fixtures not supported (maybe in the future)")

        if isinstance(function, FixtureFunctionDefinition):
            raise ValueError(
                f"@pytest.fixture is being applied more than once to the same function {function.__name__!r}"
            )

        if hasattr(function, "pytestmark"):
            fail(
                "Marks cannot be applied to fixtures.\n"
                "See docs: https://docs.pytest.org/en/stable/deprecations.html#applying-a-mark-to-a-fixture-function"
            )

        fixture_definition = FixtureFunctionDefinition(
            function=function, fixture_function_marker=self, _ispytest=True
        )

        name = self.name or function.__name__
        if name == "request":

View on GitHub (pinned to 0d6fbdeffa)