简体   繁体   English

Pytest 类实例级夹具内部参数化 class

[英]Pytest class-instance level fixture inside parametrized class

I have a following simplified code example:我有以下简化的代码示例:

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

What I would like to do is to execute UI actions in the authorization_code function once and obtain one access_token per instance.我想做的是在authorization_code码 function 中执行一次 UI 操作,并为每个实例获取一个 access_token。

Currently my UI actions are executed for every test case, leading to the fact that UI actions actually execute 2 * 2 = 4 times.目前,我的 UI 操作针对每个测试用例执行,导致 UI 操作实际执行 2 * 2 = 4 次。

Is it possible to do with pytest?可以用 pytest 做吗?
Or maybe I am missing something in my setup?或者我的设置中遗漏了一些东西?

In general I would just change the fixture scope: currently it gets recreated every time it is called, hence the reuse of ui actions.一般来说,我只会更改夹具 scope:目前每次调用它都会重新创建它,因此可以重用 ui 操作。 This is by design to ensure fixtures are clean.这是为了确保固定装置清洁而设计的。 If your fixture didn't depend on the function-level fixture instance you could just put scope="class" .如果您的夹具不依赖于功能级夹具instance ,您可以只放置scope="class" (See the docs on scopes ). (请参阅有关范围的文档)。

In this case I'd be tempted to handle the caching myself:在这种情况下,我很想自己处理缓存:

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 is just used to prove that we don't regenerate the fixture). which只是用来证明我们没有重新生成夹具)。

This feels inelegant and I'm open to better ways of doing it.这感觉不优雅,我愿意接受更好的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM