> 文档中心 > pytest系列教程——9、 参数化 @pytest.mark.parametrize

pytest系列教程——9、 参数化 @pytest.mark.parametrize


问题背景

当我们写好一个函数进行自测的时候,通常需要多种数据场景进行验证,例如我写了一个乘法计算器函数:

import pytestdef func(a: int, b: int):    return a*bdef test01():    assert func(1, 2) == 2    assert func(2, 2) == 4    assert func(3, 2) == 6    assert func(4, 2) == 9if __name__ == '__main__':    pytest.main(['参数化.py', '-s'])

执行结果

collected 1 item参数化.py F================================== FAILURES ===================================___________________________________ test01 ____________________________________def test01():assert func(1, 2) == 2assert func(2, 2) == 4assert func(3, 2) == 6>assert func(4, 2) == 9Eassert 8 == 9E +  where 8 = func(4, 2)参数化.py:22: AssertionError=========================== short test summary info ===========================FAILED 参数化.py::test01 - assert 8 == 9============================== 1 failed in 0.22s ==============================***Repl Closed***

通过在测试用例中输入不同的测试数据,进行场景编写,可实现所需要的目的。但是,这样的,测试用例维护性不强,耦合度高,可拓展性低,如果某天对func()函数进行重构,则涉及到的用例全部需要维护。

@pytest.mark.parametrize进行参数化

pytest提供@pytest.mark.parametriza 可以实现参数化:

import pytestdef func(a: int, b: int):    return a*b@pytest.mark.parametrize("intA,intB,expected",[(1,2,2),(2,2,4),(3,3,9),(4,4,15)])def test01(intA,intB,expected):    print(f"{intA}*{intB}={expected}")    assert func(intA,intB) == expectedif __name__ == '__main__':    pytest.main(['参数化.py', '-s'])

执行结果:

collected 4 items参数化.py  1*2=2.2*2=4.3*3=9.4*4=15F================================== FAILURES ===================================_______________________________ test01[4-4-15] ________________________________intA = 4, intB = 4, expected = 15    @pytest.mark.parametrize("intA,intB,expected",[(1,2,2),(2,2,4),(3,3,9),(4,4,15)])    def test01(intA,intB,expected): print(f"{intA}*{intB}={expected}")>assert func(intA,intB) == expectedEassert 16 == 15E +  where 16 = func(4, 4)参数化.py:20: AssertionError=========================== short test summary info ===========================FAILED 参数化.py::test01[4-4-15] - assert 16 == 15========================= 1 failed, 3 passed in 0.22s =========================***Repl Closed***

使用实例

import pytestdef loginDemo(loginName: str, password: str):    if loginName == "admin" and password == "123456": return {"success": True, "loginInfo": "admin用户登录成功"}    elif loginName == "tester" and password == "123123": return {"success": True, "loginInfo": "tester用户登录成功"}    else: return {"success": False, "loginInfo": "该用户不允许登录或密码错误"}data = [{"loginName": "admin", "password": "123456"}, {"loginName": "tester", "password": "123123"}, {"loginName": "hello", "password": "123456"}]@pytest.mark.parametrize('dic', data)def test01(dic):    assert loginDemo(dic['loginName'],dic['password'])['success'] == Trueif __name__ == '__main__':    pytest.main(['参数化.py', '-s'])

执行结果:

collected 3 items参数化.py ..F================================== FAILURES ===================================________________________________ test01[dic2] _________________________________dic = {'loginName': 'hello', 'password': '123456'}    @pytest.mark.parametrize('dic', data)    def test01(dic):>assert loginDemo(dic['loginName'],dic['password'])['success'] == TrueEassert False == True参数化.py:20: AssertionError=========================== short test summary info ===========================FAILED 参数化.py::test01[dic2] - assert False == True========================= 1 failed, 2 passed in 0.21s =========================***Repl Closed***