I have a base test class that implements some tests that i want to re-use. Idea is to inherit from this class and override a fixture to provide necessary input data to the base class tests. Something like this:
base_class.py
class TestBase:
@pytest.fixture(scope="module")
def base_settings(self) -> dict:
return None
def test_settings(base_settings):
assert base_settings["value_a"] > base_settings["value_b"]
test_my_class.py
class TestMyClass(TestBase):
# override the base_settings fixture in TestBase
@pytest.fixture(scope="module")
def base_settings(self) -> dict:
return {"value_a": 4, "value_b": 3}
}
When i now execute test_my_class.py I would expect the test_settings
test to pass (value_a is greater than value_b) but instead it complains that base_settings is None -> fixture from base class is used instead of the one in TestMyClass. How can i fix this? I also tried passing parameters via __init__
method but it seems like this is not supported in pytest.
I've just tested in pytest 8.0.1 and it works the way you expect. What might be happening is that pytest executes your TestBase
by itself, simply because you named it Test...
and it therefore gets collected as any other test class.
In the following example 2 tests are run, with one failing as expected not because it gets None
but because I set both value_a
and value_b
to 3
just to prove that the fixture was indeed overridden between individual test classes:
import pytest
class Base:
@pytest.fixture(scope="class")
def base_settings(self) -> dict:
return None
def test_settings(self, base_settings):
assert base_settings["value_a"] > base_settings["value_b"]
class TestMyClassA(Base):
@pytest.fixture(scope="class")
def base_settings(self) -> dict:
return {"value_a": 4, "value_b": 3}
class TestMyClassB(Base):
@pytest.fixture(scope="class")
def base_settings(self) -> dict:
return {"value_a": 3, "value_b": 3}
Note: I changed scope
to class
because it seems more logical but the original module
should work as well.