【问题标题】:How to find the test ID for parametrized tests during execution of the test?如何在测试执行期间找到参数化测试的测试 ID?
【发布时间】:2019-06-05 18:27:30
【问题描述】:

我有一个使用@pytest.mark.parametrize 参数化的测试,以便可以使用不同的参数执行相同的测试功能。 @pytest.mark.parametrize 使用定义为函数的 ids 参数,以便为每个参数生成自定义测试 ID。

我的测试函数将一个文件写入磁盘,以表格形式列出给定参数的实际结果和预期结果之间的差异。我想在文件中报告测试 ID。

是否有我可以调用的 API 来告诉我哪个测试 ID 适用于特定的测试执行?

【问题讨论】:

标签: python pytest


【解决方案1】:

您可以使用Request Fixture 中的request.node.callspec.id

但请注意,该值取决于ids 函数“生成字符串表示以成为测试 ID 的一部分”的方式。从 Different options for test IDs 上的 pytest 文档中,通常会将参数的字符串化版本添加到测试 ID。

例如,如果ids 函数生成的 ID 不包含字符串化参数或不依赖于其他任何内容:

import random
def generate_random_id(param) -> str:
    return f'{random.randint(1,100)}'

testdata = ['argA', 'argB']

@pytest.mark.parametrize('param', testdata, ids=generate_random_id)
def test_foo(param, request):
    print(request.node.callspec.id)

然后您将按原样获取生成的 ID:

tests/test_a.py::test_foo[78] PASSED      
tests/test_a.py::test_foo[10] PASSED      

============================ PASSES =============================
_________________________ test_foo[78] __________________________
--------------------- Captured stdout call ----------------------
78
_________________________ test_foo[10] __________________________
--------------------- Captured stdout call ----------------------
10

如果ids 函数包含参数的字符串表示,那么您将需要某种分隔符来手动拆分参数和测试 ID:

import random
def generate_random_id(param):
    test_id = random.randint(1, 100)
    return f'{param}-{test_id}'  

testdata = ['argA', 'argB']

@pytest.mark.parametrize('param', testdata, ids=generate_random_id)
def test_foo(param, request):
    param, test_id = request.node.callspec.id.split('-')
    print(param)
    print(test_id)
tests/test_a.py::test_foo[argA-43] PASSED 
tests/test_a.py::test_foo[argB-37] PASSED 

============================ PASSES =============================
_______________________ test_foo[argA-43] _______________________
--------------------- Captured stdout call ----------------------
argA
43
_______________________ test_foo[argB-37] _______________________
--------------------- Captured stdout call ----------------------
argB
37

如果有多个参数,那么它会变得更加复杂,因为所有参数 + ids 组合都连接在一起以创建完整的测试 ID。您将需要一个不同于- 的单独分隔符:

import random
def generate_random_id(param):
    test_id = random.randint(1, 100)
    return f'{param}+{test_id}'  # Use '+' to separate param+ID

testdata = [
    ('argA', 'argB'),
    ('argC', 'argD'),
]

@pytest.mark.parametrize('param1, param2', testdata, ids=generate_random_id)
def test_foo(param1, param2, request):
    print(request.node.callspec.id)
    params = request.node.callspec.id.split('-')
    for a_param in params:
        param, test_id = a_param.split('+')
        print(param)
        print(test_id)
tests/test_a.py::test_foo[argA+70-argB+25] PASSED         
tests/test_a.py::test_foo[argC+97-argD+30] PASSED          

===================================== PASSES =====================================
___________________________ test_foo[argA+70-argB+25] ____________________________
------------------------------ Captured stdout call ------------------------------
argA+70-argB+25
argA
70
argB
25
___________________________ test_foo[argC+97-argD+30] ____________________________
------------------------------ Captured stdout call ------------------------------
argC+97-argD+30
argC
97
argD
30

【讨论】:

    【解决方案2】:

    你可以使用:

    os.environ.get('PYTEST_CURRENT_TEST')
    

    获取当前参数化执行。

    已经提出了一个类似的问题,并且有很多其他选择:py.test: how to get the current test's name from the setup method?

    如果您正在寻找一种更动态的方法,请查看:https://hackebrot.github.io/pytest-tricks/param_id_func/,这是一个 pytest 插件,可以减轻痛苦。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-15
      • 1970-01-01
      相关资源
      最近更新 更多