pytest合集(7)— 测试用例参数化

1、pytest.mark.parametrize()

语法糖:

parametrize(argnamesargvaluesindirect=Falseids=Nonescope=None*_param_mark=None)

argnames:参数名,以逗号分隔的字符串,表示一个或多个参数名称。或参数字符串组成的列表/元组。

        如果是一个参数,使用参数名的字符串。

        如果是多个参数,多个参数名之间使用逗号分隔的字符串,或者多个参数名组成的列表,或者多个参数名组成的元组。

argvalues:参数值,类型是一个可迭代对象,和参数名一一对应。

        如果argnames为一个参数,则argvalues是一个列表。

        如果argnames为多个参数,则argvalues必须是一个嵌套元组的列表,其中每个元组元素值与参数名一一对应。

indirect:参数名称列表(参数名称的子集)或布尔值。

        indirect一般与Pytest的fixture,request.param组合使用

        当indrect =True时,argnames参数名是fixture夹具的函数名,argvalues则是给这个夹具函数传递的参数。

ids:标记参数化测试用例的执行名称,默认自动生成,多个参数名之间用"-"连接。

scope:参数范围。

1、单个参数名

新建 test_parametrize.py 文件如下:

import pytest


# 单个参数名
@pytest.mark.parametrize('a', [1, 2, 3])
def test_one(a):
    print(a)

运行命令:pytest test_parametrize.py -vs

collected 3 items                                                                                                                                                   

test_parametrize.py::test_one[1] 1        PASSED
test_parametrize.py::test_one[2] 2        PASSED
test_parametrize.py::test_one[3] 3        PASSED

说明:

argnames参数名只有一个参数的时候,使用参数名的字符串,argvalues参数值使用一个列表。

测试用例test_one使用装饰器parametrize,pytest每次运行测试用例的时候,参数名a都会从参数值[1,2,3]中取出一个值来运行子用例。

2、多个参数名

修改 test_parametrize.py 文件如下:

import pytest


# 多个参数名
@pytest.mark.parametrize("a,b", [('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')])
# @pytest.mark.parametrize(['a', 'b'], [('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')])
# @pytest.mark.parametrize(('a', 'b'), [('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')])
def test_two(a, b):
    print(a, b)

运行命令:pytest test_parametrize.py -vs

collected 3 items                                                                                                                                                   

test_parametrize.py::test_two[a1-b1] a1 b1        PASSED
test_parametrize.py::test_two[a2-b2] a2 b2        PASSED
test_parametrize.py::test_two[a3-b3] a3 b3        PASSED

说明:

argnames参数名有多个的时候,多个参数名之间使用逗号分隔的字符串,多个参数名组成的列表,多个参数名组成的元组,这三种写法都可以。

argnames参数名有多个的时候,argvalues必须是一个嵌套元组的列表,其中每个元组元素值与参数名一一对应。

ids参数,表示测试用例名称,默认自动生成,多个参数名之间用"-"连接。

pytest运行的时候,parametrize装饰的测试用例test_two依次从参数值列表[('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')]中取出3个元组,运行3次测试用例。

3、indrect =True,与fixture和request组合使用

修改 test_parametrize.py 文件如下:

import pytest


# 夹具参数化
@pytest.fixture()
def fixture_demo(request):
    return request.param + 1


lst = [1, 2, 3]


# indirect=True,argnames作为参数传入参数名对应的夹具函数
@pytest.mark.parametrize('fixture_demo', lst, indirect=True)
def test_three(fixture_demo):
    print(fixture_demo)

运行命令:pytest test_parametrize.py -vs

collected 3 items                                                                                                                                                   

test_parametrize.py::test_three[1] 2        PASSED
test_parametrize.py::test_three[2] 3        PASSED
test_parametrize.py::test_three[3] 4        PASSED

说明:

当indrect =True时,argnames参数名是fixture夹具的函数名,argvalues则是给这个夹具函数传递值的参数。

夹具pytest.fixture(params) 可以用来实现参数化,参数化的时候这里需要用到一个参数request,用来接收fixture返回的结果,通过request.param来接收夹具对象的参数值。

4、装饰测试类

修改 test_parametrize.py 文件如下:

import pytest


# 装饰类需要注意参数要和类中的所有测试函数保持一致
@pytest.mark.parametrize("a,b", [('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')])
class TestClass:
    def test_four(self, a, b):
        print(a, b)

    def test_five(self, a, b):
        print(a + b)

运行命令:pytest test_parametrize.py -vs

collected 6 items                                                                                                                                                   

test_parametrize.py::TestClass::test_four[a1-b1] a1 b1        PASSED
test_parametrize.py::TestClass::test_four[a2-b2] a2 b2        PASSED
test_parametrize.py::TestClass::test_four[a3-b3] a3 b3        PASSED
test_parametrize.py::TestClass::test_five[a1-b1] a1b1        PASSED
test_parametrize.py::TestClass::test_five[a2-b2] a2b2        PASSED
test_parametrize.py::TestClass::test_five[a3-b3] a3b3        PASSED

说明:

parametrize装饰的类TestClass中的所有测试用例都调用了参数化。

5、装饰模块

修改 test_parametrize.py 文件如下:

import pytest

pytestmark = pytest.mark.parametrize("a,b", [('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')])


def test_two(a, b):
    print(a, b)


class TestClass:
    def test_four(self, a, b):
        print(a, b)

    def test_five(self, a, b):
        print(a + b)

运行命令:pytest test_parametrize.py -vs

collected 6 items                                                                                                                                                   

test_parametrize.py::TestClass::test_four[a1-b1] a1 b1        PASSED
test_parametrize.py::TestClass::test_four[a2-b2] a2 b2        PASSED
test_parametrize.py::TestClass::test_four[a3-b3] a3 b3        PASSED
test_parametrize.py::TestClass::test_five[a1-b1] a1b1        PASSED
test_parametrize.py::TestClass::test_five[a2-b2] a2b2        PASSED
test_parametrize.py::TestClass::test_five[a3-b3] a3b3        PASSED

说明:

使用全局变量pytestmark = pytest.mark.parametrize(),可以参数化模块中的所有测试用例。

6、使用内置mark.xfail,在参数化中标记测试用例预期执行失败

修改 test_parametrize.py 文件如下:

import pytest


# 使用内置mark.xfail,在参数化中标记单个测试用例预期执行失败
@pytest.mark.parametrize("test_input,expected",
                         [("3+5", 8), ("2+4", 6), pytest.param("6*9", 42, marks=pytest.mark.xfail)])
def test_eval(test_input, expected):
    assert eval(test_input) == expected

运行命令:pytest test_parametrize.py -vs

collected 3 items                                                                                                                                                   

test_parametrize.py::test_eval[3+5-8]         PASSED
test_parametrize.py::test_eval[2+4-6]         PASSED
test_parametrize.py::test_eval[6*9-42]         XFAIL

说明:

xfail 标记的测试用例预期执行失败,实际执行失败,则状态标记为XFAIL。

7、堆叠多个parametrize装饰器

修改 test_parametrize.py 文件如下:

import pytest


# 堆叠多个parametrize装饰器,在这种情况下,每次调用都会参数化所有先前的参数化。
@pytest.mark.parametrize('a', ['a1', 'a2'])
@pytest.mark.parametrize('b', ['b1', 'b2', 'b3'])
def test_over(a, b):
    print(a, b)

运行命令:pytest test_parametrize.py -vs

collected 6 items                                                                                                                                                   

test_parametrize.py::test_over[b1-a1] a1 b1        PASSED
test_parametrize.py::test_over[b1-a2] a2 b1        PASSED
test_parametrize.py::test_over[b2-a1] a1 b2        PASSED
test_parametrize.py::test_over[b2-a2] a2 b2        PASSED
test_parametrize.py::test_over[b3-a1] a1 b3        PASSED
test_parametrize.py::test_over[b3-a2] a2 b3        PASSED

说明:

堆叠多个parametrize装饰器,在这种情况下,每次调用都会参数化所有先前的参数化。


reference:

API Reference — pytest documentation

How to parametrize fixtures and test functions — pytest documentation

你可能感兴趣的:(Pytest合集,pytest,parametrize,fixture,参数化)