使用 pytest 动态参数化类级装置

dWi*_*tty 5 python testing fixture pytest

可以从命令行参数参数化测试函数。可以将固定装置的范围限定为一个类。我想将这两件事结合起来,以便每个类都接收赋予类内固定装置的参数化参数。

(本质上,每个命令行参数我需要运行一个非常昂贵的操作,然后针对该操作的结果进行各种便宜、快速的测试,并且我不希望为每个便宜的测试重新运行昂贵的操作,所以我想要一种保存它的方法)

换句话说,我正在寻找与 pytest_generate_tests(metafunc) 等效的函数,它将用于动态参数化固定装置,而不是测试函数。

我已经尝试过但不成功的一件事是读取请求参数并通过 pytest_generate_tests 挂钩设置这些参数。

conftest.py:
    def pytest_generate_tests(metafunc):
        metafunc.parametrize("result", [
                (1,0),(1,2)
            ])

test_thing.py:
    class TestThingy:
        @pytest.fixture(scope="class")
        def result(self, request):
            a,b=request.param
            return a+b

    #@pytest.mark.parametrize("result", [(0, 1), (1, 2)])
    def test_one(self, result):
        assert result!=2
Run Code Online (Sandbox Code Playgroud)

运行此测试会导致出现以下错误(请注意,当我在没有 conftest 挂钩且注释行未注释的情况下尝试时,测试运行良好):

@pytest.fixture(scope="class")
def result(self, request):
    a,b=request.param
Run Code Online (Sandbox Code Playgroud)

AttributeError:“SubRequest”对象没有属性“param”

我也对任何其他替代方法来实现相同的结果感兴趣。

Cla*_*sen 4

我已经完成了一项基于命令行参数的夹具参数化工作,如下所示:

# contents of conftest.py
import pytest

def pytest_addoption(parser):
    parser.addoption("--test-local", action="store_true", default=False)

def pytest_generate_tests(metafunc):
    if "dummy" in metafunc.fixturenames:
        #driverParams sets dummy[0], dummy[1] parametrically (as seen below)
        if metafunc.config.getoption("--test-local"):
            driverParams = [(True, None)]
        else:
            driverParams = [(False, "seriousface setting 1"), 
                            (False, "seriousface setting 2")]
        metafunc.parametrize("dummy", driverParams)

#driver can then be used as a standard fixture
@pytest.fixture(scope="function")
def driver(dummy):
    _driver = makeDriverStuff(dummy[0], dummy[1])
    yield _driver
    _driver.cleanup()

@pytest.fixture(scope="function")
def dummy():
    pass
Run Code Online (Sandbox Code Playgroud)

本质上,这里发生的事情是,当metafunc.parametrize("dummy", driverParams)运行时,它会扔进driverParams任何依赖于虚拟夹具的东西。更重要的是,这意味着虚拟固定功能从未实际执行

最初,我尝试使用 metafunc 直接参数化我的驱动程序装置,并注意到清理从未发生,因为我之前做事的(错误)方式是直接使用metafunc.parametrizewith makeDriverStuff(param1, param2),然后挠头想知道为什么driver()从未被调用。假人的目的是说,“嘿,这里有一个合法的固定装置,不要抱怨你找不到它!”,然后总是用一些真正有用的东西来抢占它。

就像我说的,这是一个丑陋的黑客行为。但你应该能够适应它