参数化和数据驱动测试

如果说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 ==============================

由结果可知,当使用多个标记时,用例数量不再是参数值的数量,而是所有标记参数的 笛卡儿积