如何通过命令行将多个列表参数传递给多个 pytest 固定装置 [英] how to pass multiple list arguments by command line to multiple pytest fixtures

查看:44
本文介绍了如何通过命令行将多个列表参数传递给多个 pytest 固定装置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将下面的列表从我的命令行传递到我的 pytest 代码(如 python 中的 argparser),谁能帮我如何做到这一点?

I want to pass below lists from my command line to my pytest code (like argparser in python), can anyone help me how to do this ?

pytest -vs test_sample.py --html=results.html --A_list=['A1', 'A2'] --B_list=['B1'] --C_list=['C1','C2']

这是我的 pytest 代码.

Here is my pytest code.

import pytest

@pytest.fixture(scope="session", params=A_list) # here A_list is a list and it has to be passed from command line
def get_A_list(request):
    print("inside fixture get_A_list - element in A_list: ".format(request.param))
    yield request.param


@pytest.fixture(scope="module", params=B_list) # here B_list is a list and it has to be passed from command line
def get_B_list(request, get_A_list):
    print("inside fixture get_B_list - element in A_list: {}, element in B_list: {}: ".format(get_A_list, request.param))
    yield request.param


@pytest.mark.parametrize("c", C_list) # here C_list is a list and it has to be passed from command line
def test_functionality(get_A_list, get_B_list, c):
    print("inside function test_functionality - element in A_list: {}, element in B_list: {}, element in C_list: {}: ".format(get_A_list, get_B_list, c))

test_functionality 是我的测试用例函数.测试用例的数量应基于命令行中传递的列表长度

test_functionality is my test case function. The number of test cases should be based on length of lists passed in command line

对于上述列表,它必须按以下顺序执行测试用例.

It has to execute test cases in below order for the above mentioned lists.

test_functionality[A1-B1-C1]
test_functionality[A1-B1-C2]
test_functionality[A2-B1-C1]
test_functionality[A2-B1-C2]

我需要使用 A_list 中的元素在 **fixture get_A_list 中执行一些操作 ....同样我需要使用 A_list 和 B_list 中的元素在 fixture get_B_list 中执行一些操作 .......这样我有 4 个装置,最后我需要在 test_functionality 中执行测试用例,它将使用 A_list 、 B_list 、 C_list 等中的元素.

I need to perform some operation in **fixture get_A_list using elements in A_list ....similarly i need to perform some operations in fixture get_B_list using elements in A_list and B_list .......like this i have 4 fixtures and finally i need to execute the test cases in test_functionality which will use elements in A_list , B_list , C_list etc..

最后输出应该如下所示..

Finally the the output should be like below ..

    inside fixture get_A_list - element in A_list: A1
    inside fixture get_B_list - element in A_list: A1, element in B_list: B1
    inside function test_functionality - element in A_list: A1, element in B_list: B1, element in C_list: C1
    inside function test_functionality - element in A_list: A1, element in B_list: B1, element in C_list: C2
    inside function test_functionality - element in A_list: A1, element in B_list: B1, element in C_list: C3
    inside fixture get_A_list - element in A_list: A2
    inside fixture get_B_list - element in A_list: A2, element in B_list: B1
    inside function test_functionality - element in A_list: A2, element in B_list: B1, element in C_list: C1
    inside function test_functionality - element in A_list: A2, element in B_list: B1, element in C_list: C2
    inside function test_functionality - element in A_list: A2, element in B_list: B1, element in C_list: C3

推荐答案

这里的问题是 params 参数是在加载时读取的,此时命令行参数的信息还不可用,所以你不能像在你的例子中那样设置它们.

The problem here is that the params argument is read at load time, where the information about command line parameters is not yet available, so you cannot just set them like in your example.

最好的方法是重构你的代码,这样就不需要了.如果您能够做到这一点,那么您就不需要额外的灯具了,

The best way is proably to restructure your code so that would not be needed. If you are able to do that so you don't need the additional fixtures,

无论如何,您首先必须注册您的命令行参数:

Anyway, you first have to register your command line arguments:

conftest.py

def pytest_addoption(parser):
    parser.addoption("--A_list", action="store")
    parser.addoption("--B_list", action="store")
    parser.addoption("--C_list", action="store")

现在,如果您可以重构您的代码,使装置不依赖于参数,您就可以根据传递的命令行参数对您的测试进行参数化.如果您将参数作为逗号分隔的列表传递,您可以执行以下操作:

Now, if you can restructure your code so that the fixtures do not depend on the parameters, you can parametrize your tests based on the passed command line arguments. Provided you pass the arguments as comma-separated lists, you can do something like this:

test.py

import pytest

@pytest.hookimpl
def pytest_generate_tests(metafunc):
    # collect fixture names with values
    option_values = {
        "a": metafunc.config.option.A_list,
        "b": metafunc.config.option.B_list,
        "c": metafunc.config.option.C_list
    }

    # add parametrization for each fixture name
    for name, value in option_values.items():
        if name in metafunc.fixturenames and value is not None:
            metafunc.parametrize(name, value.split(","))

def test_functionality1(a, b, c):
    print(a, b, c)

这将按所需顺序创建参数化测试.

This will create the parametrized tests in the desired order.

如果这不可行,您可以尝试在运行时创建夹具(参见 这篇文章 了解更多信息):

If that is not possibble, you may try to create your fixtures at runtime instead (see this post for more information):

conftest.py

# define the functions used as fixtures
def a_list_fixture(request):
    print(f"get_A_list: {request.param}")
    yield request.param

def b_list_fixture(request, get_A_list):
    print(f"get_B_list: {get_A_list},  {request.param}")
    yield request.param

# at session start, create the fixtures with the correct params
def pytest_sessionstart(session):
    a_list = session.config.option.A_list
    if a_list:
        a_list = a_list.split(",")
        name = "get_A_list"
        fn = pytest.fixture(scope='session', name=name,
                            params=a_list)(a_list_fixture)
        setattr(sys.modules[__name__], "{}_func".format(name), fn)
    b_list = session.config.option.B_list
    if b_list:
        b_list = b_list.split(",")
        name = "get_B_list"
        fn = pytest.fixture(scope='session', name=name,
                            params=b_list)(b_list_fixture)
        setattr(sys.modules[__name__], "{}_func".format(name), fn)

请注意,您仍然需要像上面一样为 c 参数化函数:

Note that you still need to parametrize the function for c as above:

test.py

import pytest

@pytest.hookimpl
def pytest_generate_tests(metafunc):
    c_value = metafunc.config.option.C_list
    if "c" in metafunc.fixturenames and value is not None:
            metafunc.parametrize("c", value.split(","))

def test_functionality(get_A_list, get_B_list, c):
    print(f"test_functionality {get_A_list}, {get_B_list}, {c}")

这将创建所需的参数化测试:

This creates the needed parametrized tests:

pytest -vv --A_list=A1,A2";--B_list="B1";--C_list="C1,C2":

================================================= test session starts =================================================
...
collected 4 items

so/cmd_line_args/test.py::test_functionality[C1-A1-B1] PASSED                                                    [ 25%]
so/cmd_line_args/test.py::test_functionality[C2-A1-B1] PASSED                                                    [ 50%]
so/cmd_line_args/test.py::test_functionality[C1-A2-B1] PASSED                                                    [ 75%]
so/cmd_line_args/test.py::test_functionality[C2-A2-B1] PASSED                                                    [100%]

================================================== 4 passed in 0.28s ==================================================

请注意,参数顺序并不符合预期,但这只是一个表面问题.下面是 print 函数的输出:

Note that the parameter order is not as desired, but this is merely a cosmetic issue. Here is the output of the print functions:

pytest -s --A_list=A1,A2";--B_list="B1";--C_list="C1,C2"

================================================= test session starts =================================================
...
collected 4 items

test.py get_A_list: A1
get_B_list: A1,  B1
test_functionality A1, B1, C1
.test_functionality A1, B1, C2
.get_A_list: A2
get_B_list: A2,  B1
test_functionality A2, B1, C1
.test_functionality A2, B1, C2
.

================================================== 4 passed in 0.27s ==================================================

这篇关于如何通过命令行将多个列表参数传递给多个 pytest 固定装置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆