书籍来源:房荔枝 梁丽丽《pytest框架与自动化测试应用》
一边学习一边整理老师的课程内容及实验笔记,并与大家分享,侵权即删,谢谢支持!
附上汇总贴:pytest框架进阶自学系列 | 汇总_热爱编程的通信人的博客-CSDN博客
通过@pytest.mark.parametrize可以实现数据驱动。@pytest.mark.parametrize的根本作用是在收集测试用例的过程中,通过对指定参数的赋值来新增被标记对象的调用(执行)。下面以例说明具体参数化时如何使用不同数据。
单一参数化应用
通常使用场景:测试方法中只有一个数据是变化的,也就是通过一个参数把多组测试数据传递进去。执行时,每组数据都执行一遍。
实现的具体步骤如下:
(1)在测试方法中输入@pytest.mark.parametrize。
(2)其中有两个参数,一个是参数名,另一个是参数值,这个值可以是多个,可以是数字或字符等。
(3)测试方法中的参数与parametrize中的参数名相同。
(4)通过参数名在测试方法中调用这些数据。
代码如下:
import pytest
@pytest.mark.parametrize("test_case", [1,2,3,'orange','apple'])
def test_string(test_case):
print("\n要测试的数据:{}".format(test_case))
一个测试用例,有多少条数据就自动执行多少遍。执行的结果如下:
D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition 2022.1.3\plugins\python-ce\helpers\pycharm\_jb_pytest_runner.py" --path D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-4/test_mark_parametrize.py
Testing started at 14:01 ...
Launching pytest with arguments D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-4/test_mark_parametrize.py in D:\SynologyDrive\CodeLearning\WIN\pytest-book\src\chapter-4
============================= test session starts =============================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1 -- D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest-book
collecting ... collected 5 items
test_mark_parametrize.py::test_string[1] PASSED [ 20%]
要测试的数据:1
test_mark_parametrize.py::test_string[2] PASSED [ 40%]
要测试的数据:2
test_mark_parametrize.py::test_string[3] PASSED [ 60%]
要测试的数据:3
test_mark_parametrize.py::test_string[orange] PASSED [ 80%]
要测试的数据:orange
test_mark_parametrize.py::test_string[apple] PASSED [100%]
要测试的数据:apple
============================== 5 passed in 0.02s ==============================
Process finished with exit code 0
多参数应用
测试输入的数据可以是表达式,输入的参数可以是多个。多个数据可以通过元组方式组织。下面是一个测试计算器的简单例子,前面两个是变量,后面是对应的数据。3+5对应的是test_input参数名,8对应的是expected参数名,下面的数据以此类推。eval将字符串str当成有效表达式来求值并返回计算结果。
代码如下:
import pytest
@pytest.mark.parametrize("test_input, expected", [("3+5", 8), ("2+5", 7), ("7*5", 30)])
def test_eval(test_input, expected):
assert eval(test_input) == expected
将其中一组数据写成错误的形式,验证断言的详细情况。执行结果如下:
D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition 2022.1.3\plugins\python-ce\helpers\pycharm\_jb_pytest_runner.py" --path D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-4/test_mark_parametrize.py
Testing started at 14:03 ...
Launching pytest with arguments D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-4/test_mark_parametrize.py in D:\SynologyDrive\CodeLearning\WIN\pytest-book\src\chapter-4
============================= test session starts =============================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1 -- D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest-book
collecting ... collected 3 items
test_mark_parametrize.py::test_eval[3+5-8]
test_mark_parametrize.py::test_eval[2+5-7]
test_mark_parametrize.py::test_eval[7*5-30] PASSED [ 33%]PASSED [ 66%]FAILED [100%]
src\chapter-4\test_mark_parametrize.py:2 (test_eval[7*5-30])
35 != 30
Expected :30
Actual :35
<Click to see difference>
test_input = '7*5', expected = 30
@pytest.mark.parametrize("test_input, expected", [("3+5", 8), ("2+5", 7), ("7*5", 30)])
def test_eval(test_input, expected):
> assert eval(test_input) == expected
E assert 35 == 30
E +35
E -30
test_mark_parametrize.py:5: AssertionError
================================== FAILURES ===================================
______________________________ test_eval[7*5-30] ______________________________
test_input = '7*5', expected = 30
@pytest.mark.parametrize("test_input, expected", [("3+5", 8), ("2+5", 7), ("7*5", 30)])
def test_eval(test_input, expected):
> assert eval(test_input) == expected
E assert 35 == 30
E +35
E -30
test_mark_parametrize.py:5: AssertionError
=========================== short test summary info ===========================
FAILED test_mark_parametrize.py::test_eval[7*5-30] - assert 35 == 30
========================= 1 failed, 2 passed in 0.06s =========================
Process finished with exit code 1
多个参数化
一个用例可以标记多个@pytest.mark.parametrize标记。
代码如下:
import pytest
@pytest.mark.parametrize('test_input', [1,2,3])
@pytest.mark.parametrize('test_output, expected', [(1,2), (3, 4)])
def test_multi(test_input, test_output, expected):
pass
实际收集到的用例是它们所有可能的组合。
代码如下:
D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition 2022.1.3\plugins\python-ce\helpers\pycharm\_jb_pytest_runner.py" --path D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-4/test_multi.py
Testing started at 14:05 ...
Launching pytest with arguments D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-4/test_multi.py in D:\SynologyDrive\CodeLearning\WIN\pytest-book\src\chapter-4
============================= test session starts =============================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1 -- D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest-book
collecting ... collected 6 items
test_multi.py::test_multi[1-2-1] PASSED [ 16%]
test_multi.py::test_multi[1-2-2] PASSED [ 33%]
test_multi.py::test_multi[1-2-3] PASSED [ 50%]
test_multi.py::test_multi[3-4-1] PASSED [ 66%]
test_multi.py::test_multi[3-4-2] PASSED [ 83%]
test_multi.py::test_multi[3-4-3] PASSED [100%]
============================== 6 passed in 0.02s ==============================
Process finished with exit code 0
参数化与fixture的结合
当一个测试方法既是注入依赖,也就是使用fixture,同时又要参数化时,使用parametrize会有冲突,此时可以通过fixture自带的参数params实现参数化。这也是参数化的一种方法,实现方法参见3.8节,应用参见8.2.5节。
pytestmark实现参数化
可以尝试通过对pytestmark赋值,参数化一个测试模块。
代码如下:
import pytest
pytestmark = pytest.mark.parametrize('test_input, expected', [(1,2),(3,4)])
def test_module(test_input, expected):
assert test_input + 1 == expected
D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition 2022.1.3\plugins\python-ce\helpers\pycharm\_jb_pytest_runner.py" --path D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-4/test_module.py
Testing started at 14:09 ...
Launching pytest with arguments D:/SynologyDrive/CodeLearning/WIN/pytest-book/src/chapter-4/test_module.py in D:\SynologyDrive\CodeLearning\WIN\pytest-book\src\chapter-4
============================= test session starts =============================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.11.0, pluggy-0.13.1 -- D:\SynologyDrive\CodeLearning\WIN\pytest-book\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\SynologyDrive\CodeLearning\WIN\pytest-book
collecting ... collected 2 items
test_module.py::test_module[1-2] PASSED [ 50%]
test_module.py::test_module[3-4] PASSED [100%]
============================== 2 passed in 0.01s ==============================
Process finished with exit code 0