簡體   English   中英

使用fixture返回值作為mark.parametrize()中的值

[英]using fixture return value as value in mark.parametrize()

我的問題是 - 是否可以使用fixture中的返回值作為參數化中的值? 問題是 - 我想動態獲取參數化的可能值(例如,虛擬服務器上的可用系統)。 當其中一個燈具創建虛擬服務器時,我可以訪問這些。 測試看起來像這樣(偽代碼):

[conftest.py]

@pytest_fixture(scope='session')
def test_server(request):
    test_server = Server([default_params])
    test_server.add()
    def fin():
        test_server.delete()
    request_addfinalizer(fin)
    return test_server()

[tests.py]

def test_basic_server(test_server):
    systems = test.server.get_available_systems()
    for system in systems:
        test_server.install(system)
        test_server.run_checks()
        test_server.uninstall(system)

def test_other(test_server):
    [other tests]

etc

這樣,為每個會話添加一個服務器,然后在其上運行所有測試,並在會話結束后刪除服務器。 但有沒有辦法在@ pytest.mark.parametrize中獲取可用的系統而不顯式列出它們(靜態地作為參數化中的列表),使用會話開始時添加的服務器中的方法? 這樣每個系統都可以在單獨的測試中運行。

我嘗試在另一個fixture中使用test_server然后返回列表(test_server fixture返回test_server的方式相同,但是我不能將它用作參數化中的值 - 因為在任何測試中調用test_server fixture之前評估decorator,並獲得該列表取決於test_server fixture。

這將是理想的:

[tests.py]

@pytest.mark.parametrize('system',[systems_list <- dynamically generated
                                             when the server is created])

def test_basic_server(test_server,system):
    test_server.install(system)
    test_server.run_checks()
    test_server.uninstall(system)

這只是一個非常基本的例子,在我的測試中,我需要根據多個場景和值進行參數化,當我靜態執行時,我最終會得到巨型數組。

但原理保持不變 - 基本上:我可以在使用此夾具運行的第一次測試之前調用夾具,或者pytest.mark.parametrize()如何訪問夾具值?

我想你可能無法直接達到你想要的效果。 因為在收集過程中會調用@pytest.mark.parametrize ,並且在收集完成后將調用fixture。

但是我有一個替代的方式來達到同樣的效果,主要是通過擴展插件pytest pytest_generate_tests和使用方法metafunc.parametrize https://pytest.org/latest/parametrize.html#basic-pytest-generate-tests-example

這是我的解決方案。 在conftest.py中

class System(object):
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "<System '{}'>".format(self.name)

def get_available_systems():
    return [System('A'), System('B'), System('C')]


def pytest_generate_tests(metafunc):
    if 'system' in metafunc.fixturenames:
        available_systems = get_available_systems()

        metafunc.parametrize('system', available_systems)

在測試文件中:

def test_basic_server(system):
    print(system)

這是輸出,您將可以訪問測試中的每個系統。

collected 3 items

test_01.py::test_basic_server[system0] <System 'A'>
PASSED
test_01.py::test_basic_server[system1] <System 'B'>
PASSED
test_01.py::test_basic_server[system2] <System 'C'>
PASSED

不好的是,每次使用夾具system時都會調用get_available_systems ,這不是你想要的。 但我認為添加一些額外的邏輯以使查詢邏輯只執行一次並不困難。

例如:

def pytest_generate_tests(metafunc):
    if 'system' in metafunc.fixturenames:
        if hasattr(metafunc.config, 'available_systems'):
            available_systems = metafunc.config.available_systems
        else:
            available_systems = get_available_systems()
            metafunc.config.available_systems = available_systems
        metafunc.parametrize('system', available_systems)

我能夠處理類似的問題,我必須生成用於即時參數化的測試數據:

class TestFilters(object):
 cls_testdata1 = []

def setup_class(cls):
 r = []
 for i in range(5):
   r.append((x, y, z))
 TestFilters.cls_testdata1 = r

@pytest.mark.parametrize("filter_id", list(range(5)))
def test_func(self, filter_id):
    params = TestFilters.cls_testdata1[filter_id]

...

這將支持動態添加參數,只需要預先確定測試次數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM