玩命加载中 . . .

pytest fixture.mark.parametrize


概述

pytest中装饰器 @pytest.mark.parametrize 可以实现测试用例参数化,类似DDT。

pytest在几个级别上支持测试参数化:

  • pytest.fixture()允许对fixture函数进行参数化

  • @pytest.mark.parametrize允许在测试函数或类中定义多组参数和fixture

  • pytest_generate_tests允许自定义参数化方案或扩展

语法格式如下:

@pytest.mark.parametrize('参数名',list) 
  • 第一个参数是字符串,多个参数中间用逗号隔开

  • 第二个参数是list多组数据用元组类型;传三个或更多参数也是这样传。list的每个元素都是一个元组,元组里的每个元素和按参数顺序 一 一 对应

示例:

  • 传一个参数 @pytest.mark.parametrize(‘参数名’,list) 进行参数化

  • 传两个参数@pytest.mark.parametrize(‘参数名1,参数名2’,[(参数1_data1, 参数2_data1),(参数1_data2, 参数2_data2)]) 进行参数化

详细信息,请继续阅读下文。

使用示例

只传递一个参数

一个参数一个值

示例代码如下:

#!/usr/bin/env python
# -*- coding:UTF-8 -*-

import pytest


@pytest.mark.parametrize("name", ["Gavin"])
def test_case1(name):
    print("\n" + name)
    assert name.lower() == "gavin"

输出结果:

C:\Users\Wang>pytest -vrs --show-progress --cache-clear --full-trace C:\Users\Wang\Desktop\test_4.py
================================================= test session starts =================================================
platform win32 -- Python 3.11.4, pytest-7.4.2, pluggy-1.3.0 -- C:\Users\Wang\AppData\Local\Programs\Python\Python311\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Wang
plugins: allure-pytest-2.13.2, order-1.1.0, progress-1.2.5, repeat-0.9.1, timeout-2.1.0
collected 1 item

Desktop/test_4.py::test_case1[Gavin] PASSED                                                                      [100%]
____________________ 1 of 1 completed, 1 Pass, 0 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _____________________

================================================== 1 passed in 0.02s ==================================================

C:\Users\Wang>

一个参数多个值

这种比较常见,示例代码如下:

#!/usr/bin/env python
# -*- coding:UTF-8 -*-

import pytest


@pytest.mark.parametrize("name", ["Gavin","Json","Bruce","Andy"])
def test_case1(name):
    print("\n" + name)
    assert name.lower() == "gavin"

输出结果:

C:\Users\Wang>pytest -vrs --show-progress --cache-clear C:\Users\Wang\Desktop\test_4.py
============================================================================================= test session starts ==============================================================================================
platform win32 -- Python 3.11.4, pytest-7.4.2, pluggy-1.3.0 -- C:\Users\Wang\AppData\Local\Programs\Python\Python311\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Wang
plugins: allure-pytest-2.13.2, order-1.1.0, progress-1.2.5, repeat-0.9.1, timeout-2.1.0
collected 4 items

Desktop/test_4.py::test_case1[Gavin] PASSED                                                                                                                                                               [ 25%]
_________________________________________________________________ 1 of 4 completed, 1 Pass, 0 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

Desktop/test_4.py::test_case1[Json] FAILED                                                                                                                                                                [ 50%]
_______________________________________________________________________________________________ test_case1[Json] _______________________________________________________________________________________________

name = 'Json'

    @pytest.mark.parametrize("name", ["Gavin","Json","Bruce","Andy"])
    def test_case1(name):
        print("\n" + name)
>       assert name.lower() == "gavin"
E       AssertionError: assert 'json' == 'gavin'
E         - gavin
E         + json

Desktop\test_4.py:10: AssertionError
--------------------------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------------------------

Json
_________________________________________________________________ 2 of 4 completed, 1 Pass, 1 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

Desktop/test_4.py::test_case1[Bruce] FAILED                                                                                                                                                               [ 75%]
______________________________________________________________________________________________ test_case1[Bruce] _______________________________________________________________________________________________

name = 'Bruce'

    @pytest.mark.parametrize("name", ["Gavin","Json","Bruce","Andy"])
    def test_case1(name):
        print("\n" + name)
>       assert name.lower() == "gavin"
E       AssertionError: assert 'bruce' == 'gavin'
E         - gavin
E         + bruce

Desktop\test_4.py:10: AssertionError
--------------------------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------------------------

Bruce
_________________________________________________________________ 3 of 4 completed, 1 Pass, 2 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

Desktop/test_4.py::test_case1[Andy] FAILED                                                                                                                                                                [100%]
_______________________________________________________________________________________________ test_case1[Andy] _______________________________________________________________________________________________

name = 'Andy'

    @pytest.mark.parametrize("name", ["Gavin","Json","Bruce","Andy"])
    def test_case1(name):
        print("\n" + name)
>       assert name.lower() == "gavin"
E       AssertionError: assert 'andy' == 'gavin'
E         - gavin
E         + andy

Desktop\test_4.py:10: AssertionError
--------------------------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------------------------

Andy
_________________________________________________________________ 4 of 4 completed, 1 Pass, 3 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

========================================================================================= 3 failed, 1 passed in 0.06s ==========================================================================================

C:\Users\Wang>

多个参数

多个参数多个值

下面是官网的示例:

# content of test_expectation.py
import pytest


@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
def test_eval(test_input, expected):
    assert eval(test_input) == expected

此示例,参考官网给出的另外一个方案:

https://docs.pytest.org/en/stable/how-to/parametrize.html 下 “To parametrize all tests in a module, you can assign to the pytestmark global variable:”

import pytest

pytestmark = pytest.mark.parametrize("test_input, expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])


def test_eval(test_input, expected):
    assert eval(test_input) == expected

输出结果:

C:\Users\Wang>pytest -vrs --show-progress --cache-clear C:\Users\Wang\Desktop\test_expectation.py
============================================================================================= test session starts ==============================================================================================
platform win32 -- Python 3.11.4, pytest-7.4.2, pluggy-1.3.0 -- C:\Users\Wang\AppData\Local\Programs\Python\Python311\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Wang
plugins: allure-pytest-2.13.2, order-1.1.0, progress-1.2.5, repeat-0.9.1, timeout-2.1.0
collected 3 items

Desktop/test_expectation.py::test_eval[3+5-8] PASSED                                                                                                                                                      [ 33%]
_________________________________________________________________ 1 of 3 completed, 1 Pass, 0 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

Desktop/test_expectation.py::test_eval[2+4-6] PASSED                                                                                                                                                      [ 66%]
_________________________________________________________________ 2 of 3 completed, 2 Pass, 0 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

Desktop/test_expectation.py::test_eval[6*9-42] FAILED                                                                                                                                                     [100%]
______________________________________________________________________________________________ test_eval[6*9-42] _______________________________________________________________________________________________

test_input = '6*9', expected = 42

    @pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
    def test_eval(test_input, expected):
>       assert eval(test_input) == expected
E       AssertionError: assert 54 == 42
E        +  where 54 = eval('6*9')

Desktop\test_expectation.py:7: AssertionError
_________________________________________________________________ 3 of 3 completed, 2 Pass, 1 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

========================================================================================= 1 failed, 2 passed in 0.03s ==========================================================================================

C:\Users\Wang>

多个参数的混合使用

示例代码如下(在官方示例代码上做了调整):

import pytest


@pytest.mark.parametrize("x", [0, 1])
@pytest.mark.parametrize("y", [2, 3])
def test_foo(x, y):
    print("Generate new combinations : {},{}".format(x, y))

上面示例会产生4个测试用例,输出结果参考如下:

C:\Users\Wang>pytest -vrs --show-progress --cache-clear C:\Users\Wang\Desktop\test_5.py
============================================================================================= test session starts ==============================================================================================
platform win32 -- Python 3.11.4, pytest-7.4.2, pluggy-1.3.0 -- C:\Users\Wang\AppData\Local\Programs\Python\Python311\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Wang
plugins: allure-pytest-2.13.2, order-1.1.0, progress-1.2.5, repeat-0.9.1, timeout-2.1.0
collected 4 items

Desktop/test_5.py::test_foo[2-0] PASSED                                                                                                                                                                   [ 25%]
_________________________________________________________________ 1 of 4 completed, 1 Pass, 0 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

Desktop/test_5.py::test_foo[2-1] PASSED                                                                                                                                                                   [ 50%]
_________________________________________________________________ 2 of 4 completed, 2 Pass, 0 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

Desktop/test_5.py::test_foo[3-0] PASSED                                                                                                                                                                   [ 75%]
_________________________________________________________________ 3 of 4 completed, 3 Pass, 0 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

Desktop/test_5.py::test_foo[3-1] PASSED                                                                                                                                                                   [100%]
_________________________________________________________________ 4 of 4 completed, 4 Pass, 0 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

============================================================================================== 4 passed in 0.02s ===============================================================================================

C:\Users\Wang>

再看个示例:

data1 = [1, 2]
data2 = ["python", "Shell"]
data3 = ["Software", "Test", Engineer", "from", "Gavin"]


@pytest.mark.parametrize("a", data1)
@pytest.mark.parametrize("b", data2)
@pytest.mark.parametrize("c", data3)
def test_case3(a, b, c):
    print("[{a} {b} {c}]")

如上示例,会产生20个测试用例。

参数化

传入字典数据

示例代码:

import pytest


json=({"username":"Json","password":"Python@666"},{"username":"Alex","password":"226699"},{"username":"Rita","password":"123456"})

@pytest.mark.parametrize('json', json)
def test_pytest_parametrize(json):
    print(f'dit : \n{json}')
    print(f'username : {json["username"]}, password : {json["password"]}')

输出结果:

C:\Users\Wang>pytest -vs --show-progress --cache-clear C:\Users\Wang\Desktop\test_pytest_parameter.py
============================================================================================= test session starts ==============================================================================================
platform win32 -- Python 3.11.4, pytest-7.4.2, pluggy-1.3.0 -- C:\Users\Wang\AppData\Local\Programs\Python\Python311\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Wang
plugins: allure-pytest-2.13.2, order-1.1.0, progress-1.2.5, repeat-0.9.1, timeout-2.1.0
collected 3 items

Desktop/test_pytest_parameter.py::test_pytest_parametrize[json0] dit :
{'username': 'Json', 'password': 'Python@666'}
username : Json, password : Python@666
PASSED
_________________________________________________________________ 1 of 3 completed, 1 Pass, 0 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

Desktop/test_pytest_parameter.py::test_pytest_parametrize[json1] dit :
{'username': 'Alex', 'password': '226699'}
username : Alex, password : 226699
PASSED
_________________________________________________________________ 2 of 3 completed, 2 Pass, 0 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

Desktop/test_pytest_parameter.py::test_pytest_parametrize[json2] dit :
{'username': 'Rita', 'password': '123456'}
username : Rita, password : 123456
PASSED
_________________________________________________________________ 3 of 3 completed, 3 Pass, 0 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

============================================================================================== 3 passed in 0.02s ===============================================================================================

C:\Users\Wang>

集合标记

示例代码:

import pytest


@pytest.mark.parametrize("username,password",
                         [("Json", "123456"), ("Jack", "654321"),
                          pytest.param("Bruce", "123456", marks=pytest.mark.xfail),
                          pytest.param("Alex", "123456", marks=pytest.mark.skip)])
def test_login(username, password):
    print(username + " : " + password)
    assert username == "Jack"

输出结果:

C:\Users\Wang>pytest -vs --show-progress --cache-clear C:\Users\Wang\Desktop\test_multi_parameter.py
============================================================================================= test session starts ==============================================================================================
platform win32 -- Python 3.11.4, pytest-7.4.2, pluggy-1.3.0 -- C:\Users\Wang\AppData\Local\Programs\Python\Python311\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Wang
plugins: allure-pytest-2.13.2, order-1.1.0, progress-1.2.5, repeat-0.9.1, timeout-2.1.0
collected 4 items

Desktop/test_multi_parameter.py::test_login[Json-123456] Json : 123456
FAILED
___________________________________________________________________________________________ test_login[Json-123456] ____________________________________________________________________________________________

username = 'Json', password = '123456'

    @pytest.mark.parametrize("username,password",
                             [("Json", "123456"), ("Jack", "654321"),
                              pytest.param("Bruce", "123456", marks=pytest.mark.xfail),
                              pytest.param("Alex", "123456", marks=pytest.mark.skip)])
    def test_login(username, password):
        print(username + " : " + password)
>       assert username == "Jack"
E       AssertionError: assert 'Json' == 'Jack'
E         - Jack
E         + Json

Desktop\test_multi_parameter.py:10: AssertionError
_________________________________________________________________ 1 of 4 completed, 0 Pass, 1 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

Desktop/test_multi_parameter.py::test_login[Jack-654321] Jack : 654321
PASSED
_________________________________________________________________ 2 of 4 completed, 1 Pass, 1 Fail, 0 Skip, 0 XPass, 0 XFail, 0 Error, 0 ReRun _________________________________________________________________

Desktop/test_multi_parameter.py::test_login[Bruce-123456] Bruce : 123456
XFAIL
_________________________________________________________________ 3 of 4 completed, 1 Pass, 1 Fail, 0 Skip, 0 XPass, 1 XFail, 0 Error, 0 ReRun _________________________________________________________________

Desktop/test_multi_parameter.py::test_login[Alex-123456] SKIPPED (unconditional skip)
_________________________________________________________________ 4 of 4 completed, 1 Pass, 1 Fail, 1 Skip, 0 XPass, 1 XFail, 0 Error, 0 ReRun _________________________________________________________________

=========================================================================================== short test summary info ============================================================================================
FAILED Desktop/test_multi_parameter.py::test_login[Json-123456] - AssertionError: assert 'Json' == 'Jack'
============================================================================== 1 failed, 1 passed, 1 skipped, 1 xfailed in 0.05s ===============================================================================

C:\Users\Wang>

项目实践

如下为在产品测试中使用到的 parameter 实战示例:

    @pytest.mark.parametrize('object_quota',
                             [-1, 0, 1, 1000, 1000000, 1000000000, 1000000000000, 1000000000000000, 1000000000000000000,
                              7168000000000000000])
    @pytest.mark.parametrize('size_quota',
                             [-1,0, 1024, 1048576, 1073741824, 1099511627776, 1125899906842624, 8070450532247928832])
    #@pytest.mark.parametrize('object_quota', [-1, 1])
    #@pytest.mark.parametrize('size_quota',[-1])
    def test_8_0_10647(self, object_quota, size_quota):
        logger.info("8_0-10647:Set value on User Max Size, User Max Objects, Bucket Max Size, Bucket Max Objects fielAccount Quota")
        TestClass.AccountCount = TestClass.AccountCount + 1
        account = "test_8_0_10604_" + str(self.rand_num) + "_" + str(TestClass.AccountCount)
        logger.info("Account: %s", account)
        self.cluster_api.Create_Account(account)
        self.radows.Set_Account_Quota(account, object_quota, size_quota)
        self.radows.Set_Account_Bucket_Quota(account, object_quota, size_quota)
        self.check_cluster_api.Check_Account_Quota(account, object_quota, size_quota)

文章作者: Gavin Wang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Gavin Wang !
  目录