pytest.mark 必须作为装饰器直接作用于测试函数或类,不可写在函数外部;可叠加多个标记,执行时用 -m "mark1 and mark2" 等布尔表达式筛选;未注册标记会触发警告,需在 pytest.ini 或 pyproject.toml 中声明以避免。

pytest.mark 能不能直接用在函数外面
不能。所有 pytest.mark 必须装饰在测试函数或类上,写在函数定义之外会报 SyntaxError 或被 pytest 忽略。常见错误是把标记写成独立语句,比如:
pytest.mark.smoke # ❌ 无效,不会生效 def test_login(): ...
正确写法只能是装饰器形式:
@pytest.mark.smoke def test_login(): ...
怎么给测试函数加多个标记并按组合筛选
支持叠加多个 pytest.mark,执行时可用 -m 配合布尔表达式筛选。例如同时打 smoke 和 auth 标记:
@pytest.mark.smoke @pytest.mark.auth def test_login_success(): ...
运行命令示例:
立即学习“Python免费学习笔记(深入)”;
-
pytest -m "smoke"—— 运行所有带smoke的用例 -
pytest -m "smoke and auth"—— 同时满足两个标记 -
pytest -m "not slow"—— 排除slow标记
注意:表达式里的单词必须是已注册的标记名,否则 pytest 会警告 Unknown marker,但默认仍会执行(除非配置了 --strict-markers)。
为什么加了 @pytest.mark.xxx 却提示 Unknown marker
这是 pytest 的安全机制——未显式注册的标记名会被识别为“未知”,仅警告不报错。要彻底避免该提示并启用严格校验,需在 pyproject.toml 或 pytest.ini 中声明:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
[tool:pytest]
markers =
smoke: end-to-end smoke tests
auth: authentication-related tests
slow: tests that take >1s to run或者用 pytest.ini:
[pytest]
markers =
smoke
auth
slow注册后,拼写错误会直接报错,而不是静默忽略;加上 --strict-markers 参数还能让未知标记导致运行失败。
如何在 fixture 或参数化中动态加标记
不能直接在 @pytest.mark.parametrize 内部写 @pytest.mark.xxx,但可以用 marks 参数为单个参数组合附加标记:
@pytest.mark.parametrize("username,password,expected", [
("admin", "123", True),
pytest.param("guest", "", False, marks=pytest.mark.xfail(reason="empty password should fail")),
], ids=["valid", "invalid_empty"])
def test_login(username, password, expected): ...也可以在 fixture 中通过 request.node.add_marker() 动态添加,适用于需要根据运行时条件打标的情况:
@pytest.fixture
def setup_env(request):
if os.getenv("CI"):
request.node.add_marker(pytest.mark.ci)
yield注意:动态标记必须在测试函数开始前完成(通常在 fixture setup 阶段),且不能用于跳过或修改 pytest 收集阶段的行为。
标记本身不改变测试逻辑,但会影响收集、筛选和报告。最容易被忽略的是标记未注册带来的静默失效,以及参数化中误以为能直接装饰单个用例而漏用 marks 参数。

















