Pytest class-参数化 class 内的实例级夹具

Pytest class-instance level fixture inside parametrized class

我有以下简化代码示例:

from urllib.parse import urlparse, parse_qs
from selenium import webdriver
import pytest

@pytest.fixture(scope="module")
def driver():
    options = webdriver.ChromeOptions()
    _driver = webdriver.Chrome(options=options)
    yield _driver
    _driver.close()

@pytest.mark.parametrize("instance_name", ["instance1", "instance2"])
class TestInstance:
    @pytest.fixture
    def authorization_code(self, instance_name, driver):
        driver.get(f"https://{instance_name}.com")
        ...do some UI actions here
        authorization_code = parse_qs(urlparse(redirected_url).query)["code"][0]

    @pytest.fixture
    def access_token(self, authorization_code):
        ...obtain access_token here using authorization code
        return "access_token"

    def test_case_1(self, access_token):
        ...do some API calls using access_token

    def test_case_2(self, access_token):
        ...do some API calls using access_token

我想做的是在authorization_code函数中执行一次UI动作,每个实例获得一个access_token。

目前我的 UI 动作针对每个测试用例执行,导致 UI 动作实际执行 2 * 2 = 4 次。

是否可以用pytest来做?
或者我的设置中可能遗漏了什么?

一般来说,我只会更改夹具范围:目前每次调用时都会重新创建它,因此会重用 ui 操作。这是设计使然,以确保固定装置清洁。如果您的灯具不依赖于 function-level 灯具 instance,您可以只放置 scope="class"。 (参见docs on scopes)。

在这种情况下,我很想自己处理缓存:

import pytest
from datetime import datetime


@pytest.mark.parametrize("instance", ("instance1", "instance2"))
class TestClass:
    @pytest.fixture()
    def authcode(self, instance, authcodes={}, which=[0]):
        if not instance in authcodes:
            authcodes[
                instance
            ] = f"authcode {which[0]} for {instance} at {datetime.now()}"
            which[0] += 1
        return authcodes[instance]

    def test1(self, authcode):
        print(authcode)

    def test2(self, authcode):
        print(authcode)

which只是用来证明我们不重新生成fixture)

这感觉不雅,我愿意接受更好的方法。