pytest 内置和自定义marker
pytest 内置和自定义marker
可以通过命令行查看所有marker,包括内置和自定义的
pytest --markers
内置marker包括usefixtures 、filterwarnings 、skip 、skipif 、xfail这5个。参数化的marker在pytest参数化中有介绍,hook的marker在pytest hook中,插件的marker(pytest-ordering、allure等)在pytest插件中。当前只需知道有以上这些分类的marker即可
内置 marker
- usefixtures:
如果我们只想把fixture注入到test中,test不直接访问fixture的时候,就需要用到usefixtures。
示例,test需要一个临时目录,但是并不需要知道这个目录具体路径在哪
# content of conftest.py import os import shutil import tempfile import pytest @pytest.fixture def cleandir(): old_cwd = os.getcwd() newpath = tempfile.mkdtemp() os.chdir(newpath) yield os.chdir(old_cwd) shutil.rmtree(newpath)
# content of test_setenv.py import os import pytest @pytest.mark.usefixtures("cleandir") class TestDirectoryInit: def test_cwd_starts_empty(self): assert os.listdir(os.getcwd()) == [] with open("myfile", "w") as f: f.write("hello") def test_cwd_again_starts_empty(self): assert os.listdir(os.getcwd()) == []
TestDirectoryInit的测试方法需要一个临时目录作为当前工作目录,在类上添加@pytest.mark.usefixtures("cleandir"),类的方法不加fixture也能有"cleandir"的效果。
usefixtures可以添加多个fixture
@pytest.mark.usefixtures("cleandir", "anotherfixture")
usefixtures可以用在pytestmark,作用域是定义所在module的所有tests
pytestmark = pytest.mark.usefixtures("cleandir")
usefixtures也可以用在pytest.ini,作用域是整个项目的所有tests
# content of pytest.ini [pytest] usefixtures = cleandir
不过需要注意的是fixture函数本身是不能用usefixtures的,如果想要嵌套fixture,只能通过在fixture修饰的函数中,添加参数这种方式。
- filterwarnings
过滤警告信息。
示例,api_v1()抛出了“api v1”的警告,test_one()函数使用filterwarnings过滤掉了
import warnings def api_v1(): warnings.warn(UserWarning("api v1, should use functions from v2")) return 1 @pytest.mark.filterwarnings("ignore:api v1") def test_one(): assert api_v1() == 1
同样可以添加到pytestmark和pytest.ini中。
- skip
跳过,不测试。
示例,skip需要添加reason
@pytest.mark.skip(reason="no way of currently testing this") def test_the_unknown(): ...
不过,更实用的方式是调用pytest.skip(reason)函数,而不是用mark,这样就可以用if判断跳不跳
def test_function(): if not valid_config(): pytest.skip("unsupported configuration")
allow_module_level 可以跳过整个module
import sys import pytest if not sys.platform.startswith("win"): pytest.skip("skipping windows-only tests", allow_module_level=True)
- skipif
if判断跳不跳,还可以用skipif。
示例,如果Python版本小于3.6就跳过测试
import sys @pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6 or higher") def test_function(): ...
如果想在summary中看到reason,需要添加-rs参数。
可以把skipif赋值给变量,然后直接引用变量,或者把变量import到其他module中使用
# content of test_mymodule.py import mymodule minversion = pytest.mark.skipif( mymodule.__versioninfo__ < (1, 1), reason="at least mymodule-1.1 required" ) @minversion def test_function(): ...
# test_myothermodule.py from test_mymodule import minversion @minversion def test_anotherfunction(): ...
skipif添加到class上,会跳过类中所有方法。
可以使用pytestmark跳过module内所有test
# test_module.py pytestmark = pytest.mark.skipif(...)
如果function有多个skipif作用,只要有一个为True,就会跳过。
- xfail
xfail就是expected fail,预期失败
@pytest.mark.xfail def test_function(): ...
执行后summary不会统计为"failed",会单独列出来。如果结果失败了,“expected to fail” (XFAIL);如果结果成功了,“unexpectedly passing” (XPASS)。但是整个执行结果是”Tests passed“。
if判断
def test_function(): if not valid_config(): pytest.xfail("failing configuration (but should work)")
值得注意的是,marker会继续执行所有test代码,pytest.xfail()函数会抛出异常,中断执行后续代码
添加condition,判断条件
@pytest.mark.xfail(sys.platform == "win32", reason="bug in a 3rd party library") def test_function(): ...
添加reason,理由
@pytest.mark.xfail(reason="known parser issue") def test_function(): ...
添加raises,抛出异常/错误
@pytest.mark.xfail(raises=RuntimeError) def test_function(): ...
添加run,禁止运行
@pytest.mark.xfail(run=False) def test_function(): ...
添加strict,严格模式,即使xpass也会强制失败,summary中有输出信息”[XPASS(strict)] “,测试结果为”Tests failed“。
@pytest.mark.xfail(strict=True) def test_function(): ...
断言成功也强制失败,确实够强势的!
可以在ini文件中定义全局strict
[pytest] xfail_strict=true
在命令行添加--runxfail,忽略xfail marker,相当于没有添加这个标记的效果,该成功就成功,该失败就失败
pytest --runxfail
自定义marker
通过注解自定义marker
# content of test_server.py import pytest @pytest.mark.webtest def test_send_http(): pass # perform some webtest test for your app def test_something_quick(): pass def test_another(): pass class TestClass: def test_method(self): pass
在命令行通过-m指定运行mark打标的test
pytest -v -m webtest
也可以反选
pytest -v -m "not webtest"
但是,这样定义的marker是未注册的!在执行后会警告,PytestUnknownMarkWarning。如果添加了命令行参数--strict-markers ,未注册的marker会报错。
可以在pytest.ini文件中注册,冒号后面的所有代码都是marker说明,包括换行
[pytest] markers = slow: marks tests as slow (deselect with '-m "not slow"') webtest:marks tests with webtest(deselect with '-m "not webtest"')
更高级的,可以在pytest_configure hook函数中注册,这主要用在第三方插件
def pytest_configure(config): config.addinivalue_line( "markers", "env(name): mark test to run only on named environment" )
参考:
https://www.cnblogs.com/df888/p/13715187.html
https://www.osgeo.cn/pytest/example/markers.html
https://docs.pytest.org/en/6.2.x/mark.html
https://www.tutorialspoint.com/pytest/pytest_grouping_the_tests.htm
https://www.numpyninja.com/post/registering-custom-markers-in-pytest
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY