如何扩展pytest基类并重写fixture

0 投票
1 回答
44 浏览
提问于 2025-04-14 17:29

我有一个基础测试类,这个类里实现了一些我想重复使用的测试。我的想法是从这个类继承,并重写一个叫做“fixture”的东西,以便给基础类的测试提供必要的输入数据。大概是这样的:

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}
}

现在,当我执行 test_my_class.py 时,我希望 test_settings 测试能通过(因为 value_a 大于 value_b),但实际上它却说 base_settings 是 None——这意味着它使用了基础类里的 fixture,而不是 TestMyClass 里的那个。我该怎么解决这个问题呢?我也尝试过通过 __init__ 方法传递参数,但似乎在 pytest 中不支持这样做。

1 个回答

0

我刚刚在pytest 8.0.1中测试了一下,结果和你预期的一样。可能发生的情况是,pytest会自动执行你的TestBase这是因为你把它命名为Test...,所以它就像其他测试类一样被收集起来了。

在下面的例子中,运行了2个测试,其中一个失败是因为我把value_avalue_b都设置为3,这样做是为了证明在不同的测试类之间,测试的环境确实被覆盖了:

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}

注意:我把scope改成了class,因为这样看起来更合理,但原来的module也应该可以正常工作。

撰写回答