如何创建pytest自定义cache标记 消除测试重复样板代码
现有方案评价
你当前的实现整体逻辑通顺,可以正常完成样板代码抽离,不过存在三个可优化的问题:
- 全局设置
autouse=True的fixture会对所有用例执行marker检测,虽然性能开销可以忽略,但逻辑上不够收敛 - 执行顺序和原样板代码存在细微差异:原代码中
cache.clear()是在use_cache()上下文内部执行的,你的实现里是先退出use_cache()上下文再执行缓存清理,若清理逻辑依赖缓存上下文环境,会出现不符合预期的行为 - 没有注册自定义marker,pytest运行时会抛出「未知marker」的警告。
更优实现方案
推荐按照pytest最佳实践做如下调整,完全匹配原代码执行顺序,同时逻辑更清晰易维护:
- 首先注册自定义marker,消除pytest运行警告,代码直接写在项目根目录的
conftest.py中即可:
def pytest_configure(config): config.addinivalue_line( "markers", "cache: 标记用例自动启用缓存上下文、校验连接,用例执行完成后自动清理缓存" )
- 编写专用fixture实现缓存逻辑,不需要引入
ExitStack(当前场景只有一个上下文管理器,直接用原生with语句可读性更高),同时调整执行顺序完全对齐原样板:
import pytest @pytest.fixture def _auto_cache(): # 执行顺序完全对齐原有样板代码 with use_cache(): _check_cache_connection() # yield位置会被替换为原测试用例的执行逻辑 yield # 测试执行完成后先清缓存,再退出use_cache上下文 cache.clear()
- 自动给带
cachemarker的用例加载上述fixture,不需要全局autouse,避免无意义的逻辑执行,同样写在conftest.py中:
def pytest_collection_modifyitems(items): for item in items: if item.get_closest_marker("cache"): item.fixturenames.append("_auto_cache")
改造完成后,测试用例只需要加对应装饰器即可达到你预期的效果:
@pytest.mark.cache def test_something(self): # 原有测试逻辑,不需要再写任何缓存相关样板代码 ...
注:你原示例中写的
@pyyest.mark.cache是笔误,正确写法为@pytest.mark.cache。
简化写法(适合中小项目)
如果项目规模不大,觉得额外写pytest_collection_modifyitems麻烦,也可以直接用autouse模式,只需要修正执行顺序即可,代码更简短,性能差异在中小项目中完全可以忽略:
@pytest.fixture(autouse=True) def _auto_cache(request): if not request.node.get_closest_marker("cache"): yield return with use_cache(): _check_cache_connection() yield cache.clear()
内容的提问来源于stack exchange,提问作者Johnny Metz
相关产品推荐
相关产品推荐

