问题背景

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

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

执行结果:

  1. collected 1 item
  2. 参数化.py F
  3. ================================== FAILURES ===================================
  4. ___________________________________ test01 ____________________________________
  5. def test01():
  6. assert func(1, 2) == 2
  7. assert func(2, 2) == 4
  8. assert func(3, 2) == 6
  9. > assert func(4, 2) == 9
  10. E assert 8 == 9
  11. E + where 8 = func(4, 2)
  12. 参数化.py:22: AssertionError
  13. =========================== short test summary info ===========================
  14. FAILED 参数化.py::test01 - assert 8 == 9
  15. ============================== 1 failed in 0.22s ==============================
  16. ***Repl Closed***

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

@pytest.mark.parametrize进行参数化

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

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

执行结果:

  1. collected 4 items
  2. 参数化.py
  3. 1*2=2
  4. .2*2=4
  5. .3*3=9
  6. .4*4=15
  7. F
  8. ================================== FAILURES ===================================
  9. _______________________________ test01[4-4-15] ________________________________
  10. intA = 4, intB = 4, expected = 15
  11. @pytest.mark.parametrize("intA,intB,expected",[(1,2,2),(2,2,4),(3,3,9),(4,4,15)])
  12. def test01(intA,intB,expected):
  13. print(f"{intA}*{intB}={expected}")
  14. > assert func(intA,intB) == expected
  15. E assert 16 == 15
  16. E + where 16 = func(4, 4)
  17. 参数化.py:20: AssertionError
  18. =========================== short test summary info ===========================
  19. FAILED 参数化.py::test01[4-4-15] - assert 16 == 15
  20. ========================= 1 failed, 3 passed in 0.22s =========================
  21. ***Repl Closed***

使用实例

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

执行结果:

  1. collected 3 items
  2. 参数化.py ..F
  3. ================================== FAILURES ===================================
  4. ________________________________ test01[dic2] _________________________________
  5. dic = {'loginName': 'hello', 'password': '123456'}
  6. @pytest.mark.parametrize('dic', data)
  7. def test01(dic):
  8. > assert loginDemo(dic['loginName'],dic['password'])['success'] == True
  9. E assert False == True
  10. 参数化.py:20: AssertionError
  11. =========================== short test summary info ===========================
  12. FAILED 参数化.py::test01[dic2] - assert False == True
  13. ========================= 1 failed, 2 passed in 0.21s =========================
  14. ***Repl Closed***