参数化和数据驱动测试¶
如果说pytest中哪个标记使用最酷,那无疑是 parametrize
了,
它为用例实现了 参数化测试 的能力,进而实现了 数据驱动测试 的能力。
使用标记¶
parametrize的使用需要提供两个内容:
参数名
参数值
pytest在执行用例时,会分别将参数值,传递给参数名,以此自动的生成多个用例 。
所以参数化测试的显著结果是:用例执行数量等于参数值的数量。
# test_mark_parametrize.yaml
name: 参数化测试
mark:
- parametrize:
- n # 第一个 是参数名
- [1,2,3] # 第二个是参数值
steps:
- request:
method: get
url: http://baidu.com
执行结果如下:
(.venv) C:\demo\pytest-yaml-demo>pytest -vs
============================= test session starts ==============================
platform win32 -- Python 3.12.0, pytest-8.3.4, pluggy-1.5.0
cachedir: .pytest_cache
rootdir:
configfile: pytest.ini
plugins: yaml-1.1.0
collected 3 items
tests/parametrize/test_mark_parametrize.yaml::参数化测试[1] PASSED
tests/parametrize/test_mark_parametrize.yaml::参数化测试[2] PASSED
tests/parametrize/test_mark_parametrize.yaml::参数化测试[3] PASSED
============================== 3 passed in 0.02s ===============================
由结果可见,使用了标记的用例一共执行了3次,与parametrize标记中的参数值的数量是相等的。
使用参数¶
parametrize中的参数并不仅仅是用来控制数量的,
正如前文所述,pytest在执行用例时,会分别将参数值 传递给参数名 。
那么在用例中如何使用参数的?
可以使用 ${参数名}
的格式来使用,比如这样
# test_mark_parametrize.yaml
name: 参数化测试
mark:
- parametrize:
- n
- [1,2,3]
steps:
- request:
method: get
url: https://baidu.com?n=${n} # 使用n参数
执行结果如下:
(.venv) C:\demo\pytest-yaml-demo>pytest -vs
============================= test session starts ==============================
platform win32 -- Python 3.12.0, pytest-8.3.4, pluggy-1.5.0
cachedir: .pytest_cache
rootdir: C:\demo\pytest-yaml-demo
configfile: pytest.ini
plugins: yaml-1.1.0
collected 3 items
tests/parametrize/test_mark_parametrize.yaml::参数化测试[1] https://baidu.com?n=1
PASSED
tests/parametrize/test_mark_parametrize.yaml::参数化测试[2] https://baidu.com?n=2
PASSED
tests/parametrize/test_mark_parametrize.yaml::参数化测试[3] https://baidu.com?n=3
PASSED
============================== 3 passed in 0.02s ===============================
由结果可见,每个用例得到的 n 是不同的参数值。
加载数据文件¶
如果参数值较多,yaml用例文件可能会臃肿,不便于维护。
此时,可将参数值保存在单独数据文件中,并在yaml用例中 加载该数据文件 。
# test_mark_parametrize_load_file.yaml
name: 从文件中加载数据
mark:
- parametrize:
- n
- !include ddt_n.yaml # 默认从当前目录寻找文件,也执行绝对路径
steps:
- request:
method: get
url: https://baidu.com?n=${n} # 使用n参数
执行结果如下
(.venv) C:\demo\pytest-yaml-demo>pytest -vs
============================= test session starts ==============================
platform win32 -- Python 3.12.0, pytest-8.3.4, pluggy-1.5.0
cachedir: .pytest_cache
rootdir: C:\demo\pytest-yaml-demo
configfile: pytest.ini
plugins: yaml-1.1.0
collected 3 items
tests/parametrize/test_mark_parametrize_load_file.yaml::从文件中加载数据[4] https://baidu.com?n=4
PASSED
tests/parametrize/test_mark_parametrize_load_file.yaml::从文件中加载数据[5] https://baidu.com?n=5
PASSED
tests/parametrize/test_mark_parametrize_load_file.yaml::从文件中加载数据[6] https://baidu.com?n=6
PASSED
============================== 3 passed in 0.02s ===============================
关于 !include
有几点需要注意:
备注
支持 相对路径 和 绝对路径
相对路径是相对于 当前yaml用例所在目录
传递多个参数¶
在使用参数化时,可以 同时传递多个参数 ,
为了实现这一目标,需要将多个参数放在 共一个列表中
# test_mark_parametrize_multi_param.yaml
name: 参数化测试
mark:
- parametrize:
- x,y,z # 每次传递3个参数
- [
[1,2,3],
["a","b","c"],
["!","?","#"],
]
steps:
- request:
method: get
url: https://baidu.com?o=${x}-${y}-${z}
执行结果如下
(.venv) C:\demo\pytest-yaml-demo>pytest -vs
============================= test session starts ==============================
platform win32 -- Python 3.12.0, pytest-8.3.4, pluggy-1.5.0
cachedir: .pytest_cache
rootdir: C:\demo\pytest-yaml-demo
configfile: pytest.ini
plugins: yaml-1.1.0
collected 3 items
tests/parametrize/test_mark_parametrize_multi_param.yaml::参数化测试[1-2-3] https://baidu.com?o=1-2-3
PASSED
tests/parametrize/test_mark_parametrize_multi_param.yaml::参数化测试[a-b-c] https://baidu.com?o=a-b-c
PASSED
tests/parametrize/test_mark_parametrize_multi_param.yaml::参数化测试[!-?-#] https://baidu.com?o=!-?-#
PASSED
============================== 3 passed in 0.02s ===============================
使用多个标记¶
除了同时传递多个参数之外,也可以使用多个标记
# test_mark_parametrize_multi_mark.yaml
name: 参数化测试
mark:
- parametrize:
- x
- [1,2,3]
- parametrize:
- y
- ["a","b","c"]
- parametrize:
- z
- ["!","?","#"]
steps:
- request:
method: get
url: https://baidu.com?o=${x}-${y}-${z}
执行结果如下
(.venv) C:\demo\pytest-yaml-demo>pytest -vs
============================= test session starts ==============================
platform win32 -- Python 3.12.0, pytest-8.3.4, pluggy-1.5.0
cachedir: .pytest_cache
rootdir: C:\demo\pytest-yaml-demo
configfile: pytest.ini
plugins: yaml-1.1.0
collected 27 items
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[1-a-!] https://baidu.com?o=1-a-!
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[1-a-?] https://baidu.com?o=1-a-?
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[1-a-#] https://baidu.com?o=1-a-#
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[1-b-!] https://baidu.com?o=1-b-!
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[1-b-?] https://baidu.com?o=1-b-?
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[1-b-#] https://baidu.com?o=1-b-#
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[1-c-!] https://baidu.com?o=1-c-!
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[1-c-?] https://baidu.com?o=1-c-?
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[1-c-#] https://baidu.com?o=1-c-#
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[2-a-!] https://baidu.com?o=2-a-!
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[2-a-?] https://baidu.com?o=2-a-?
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[2-a-#] https://baidu.com?o=2-a-#
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[2-b-!] https://baidu.com?o=2-b-!
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[2-b-?] https://baidu.com?o=2-b-?
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[2-b-#] https://baidu.com?o=2-b-#
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[2-c-!] https://baidu.com?o=2-c-!
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[2-c-?] https://baidu.com?o=2-c-?
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[2-c-#] https://baidu.com?o=2-c-#
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[3-a-!] https://baidu.com?o=3-a-!
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[3-a-?] https://baidu.com?o=3-a-?
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[3-a-#] https://baidu.com?o=3-a-#
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[3-b-!] https://baidu.com?o=3-b-!
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[3-b-?] https://baidu.com?o=3-b-?
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[3-b-#] https://baidu.com?o=3-b-#
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[3-c-!] https://baidu.com?o=3-c-!
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[3-c-?] https://baidu.com?o=3-c-?
PASSED
tests/parametrize/test_mark_parametrize_multi_mark.yaml::参数化测试[3-c-#] https://baidu.com?o=3-c-#
PASSED
============================== 27 passed in 0.08s ==============================
由结果可知,当使用多个标记时,用例数量不再是参数值的数量,而是所有标记参数的 笛卡儿积 。