pytest 5.x+版本对自定义标记的管理做了更严格的规范,通过合理定义和使用自定义标记,可以精准控制测试用例的执行范围,也能根据环境、配置等条件动态跳过不需要运行的测试,大幅降低冗余测试的执行成本。

自定义标记的注册方法
在pytest 5.x+中,自定义标记需要先注册才能避免运行时出现警告,注册方式有两种,推荐在项目的pytest.ini配置文件中统一注册。
方式一:通过pytest.ini注册
在项目根目录创建或修改pytest.ini文件,添加markers配置项,每个标记占一行,可附带标记的说明。
[pytest]
markers =
smoke: 冒烟测试用例标记
regression: 回归测试用例标记
env_prod: 仅在生产环境运行的测试标记
skip_windows: 在Windows系统下跳过的测试标记
方式二:通过conftest.py注册(不推荐)
也可以在conftest.py中通过钩子函数注册,但这种方式不利于标记的全局管理,仅适合临时测试场景。
def pytest_configure(config):
config.addinivalue_line(
"markers", "smoke: 冒烟测试用例标记"
)
给测试用例添加自定义标记
注册完成后,就可以在测试用例上添加对应的自定义标记,支持函数级、类级两种添加方式。
函数级标记
直接在测试函数上方使用@pytest.mark.标记名装饰器即可。
import pytest
@pytest.mark.smoke
def test_login_success():
# 模拟登录成功场景
assert 1 == 1
@pytest.mark.regression
def test_login_fail():
# 模拟登录失败场景
assert 0 == 0
类级标记
在测试类上方添加标记,该类下所有测试方法都会继承这个标记。
import pytest
@pytest.mark.regression
class TestOrder:
def test_create_order(self):
assert True
def test_cancel_order(self):
assert True
通过标记控制测试运行
添加标记后,可以通过-m命令行参数筛选指定标记的测试用例执行,支持逻辑运算符组合筛选。
运行单个标记的测试
执行所有带smoke标记的测试用例:
pytest -m smoke
运行多个标记的测试
执行带smoke或者regression标记的测试用例:
pytest -m "smoke or regression"
执行同时带smoke和env_prod标记的测试用例:
pytest -m "smoke and env_prod"
排除特定标记的测试
执行不带regression标记的所有测试用例:
pytest -m "not regression"
通过标记实现测试跳过控制
结合自定义标记和条件判断,可以实现动态跳过测试的需求,常用的是pytest.mark.skipif装饰器配合标记判断。
基于环境跳过测试
比如env_prod标记的测试仅在生产环境运行,其他环境自动跳过:
import pytest
import os
# 判断当前是否为生产环境
is_prod = os.getenv("ENV") == "prod"
@pytest.mark.env_prod
@pytest.mark.skipif(not is_prod, reason="非生产环境跳过该测试")
def test_prod_api():
# 生产环境API测试逻辑
assert True
基于系统跳过测试
比如skip_windows标记的测试在Windows系统下自动跳过:
import pytest
import sys
@pytest.mark.skip_windows
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Windows系统不支持该测试")
def test_linux_command():
# Linux系统命令测试逻辑
assert True
在conftest.py中全局处理标记跳过
如果多个测试有统一的跳过规则,可以在conftest.py中通过钩子函数统一处理,避免重复写跳过逻辑。
import pytest
import sys
def pytest_runtest_setup(item):
# 处理skip_windows标记
if "skip_windows" in item.keywords and sys.platform.startswith("win"):
pytest.skip("Windows系统跳过该测试")
# 处理env_prod标记
if "env_prod" in item.keywords and os.getenv("ENV") != "prod":
pytest.skip("非生产环境跳过该测试")
注意事项
- 未注册的自定义标记在pytest 5.x+运行时会抛出警告,建议所有自定义标记都在
pytest.ini中注册 - 标记名不要和pytest内置标记重名,比如
skip、parametrize等,避免冲突 -m参数的表达式如果包含空格,需要用英文双引号包裹,否则会被当成多个参数解析- 标记的继承规则:类级标记会被所有子类测试方法继承,函数级标记仅对当前函数生效
常见问题排查
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 运行测试时出现PytestUnknownMarkWarning | 自定义标记未注册 | 在pytest.ini的markers中添加对应标记 |
| -m参数筛选不到对应测试 | 标记名拼写错误,或者表达式逻辑错误 | 检查标记名和表达式是否符合语法,比如逻辑运算符是否正确 |
| 跳过逻辑不生效 | 跳过条件判断错误,或者钩子函数未正确注册 | 打印条件变量的值,检查conftest.py是否在项目根目录可被pytest识别 |