You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何打印pytest fixtures的依赖关系图

pytest fixture依赖关系图构建方法

pytest支持重定义上层作用域中定义的fixture,且这类重定义会沿fixture依赖树向上传递,示例如下:

# tests/conftest.py
@pytest.fixture()
def foo(): ...
    
@pytest.fixture()
def bar(): ...
    
@pytest.fixture()
def baz(foo, bar): ...
    
@pytest.fixture()
def fizz(foo, baz, capsys): ...

# tests/deep/down/test_something.py

@pytest.fixture
def foo():
    return "something completely different"

def test_something(fizz, other, fixtures):
    # 对该测试而言,`foo`在fizz的整个依赖树中都会被替换为本地重定义的版本
    # 即fizz、baz都会接收到这个重写后的foo实例
    
@pytest.mark.parameterize("foo", ["a", "b", "c"])
def test_something_else(fizz, even, more, fixtures):
    # 参数化重定义foo的逻辑同上

这是一项灵活性极强的特性,但当fixture依赖链路较长、重定义场景较多时,很难追踪完整的依赖关系,日常开发中经常需要解答这类问题:
“从fixture foo到fizz的依赖路径是怎样的?”“当前测试依赖的fixture中,哪些会受到foo重定义的影响?”
大家熟知的pytest --fixtures tests_folder/命令只会打印指定测试目录下的所有可用fixture列表,不会展示fixture之间的依赖关系,没法直接得到类似如下结构的清晰依赖图:

foo  bar
 ^ ^   ^
 |  \ /
 |  baz    buzz
 |  ^      ^
 | /------/
fizz  

可落地的实现方案

自定义插件解析依赖

pytest内部在测试收集阶段就已经完成了所有fixture的依赖解析,你可以通过写一个极简的pytest插件来提取完整依赖关系:

  • 在pytest配置阶段拿到fixture管理器实例:session._fixturemanager,里面存储了所有作用域下的fixture定义
  • 对每个fixture定义,读取它的argnames属性,就能拿到该fixture直接依赖的所有fixture名称
  • 递归遍历依赖列表即可构建完整的依赖树,遍历过程中注意遵循pytest的fixture查找优先级:优先取离当前测试用例最近作用域的fixture定义,就能正确处理上层fixture被重定义的场景
  • 拿到依赖树结构后,既可以打印成ASCII字符图,也可以导出为通用图结构格式生成可视化图片。

如果只是临时排查单个测试用例的fixture执行顺序和依赖,也可以直接加--setup-show参数运行测试,它会按执行顺序列出所有触发的fixture,只是不会整理成清晰的树状结构。

使用现成插件

目前已有成熟的pytest插件可以直接生成fixture依赖图,安装后执行对应命令即可直接输出ASCII格式依赖树,或者导出可视化的依赖关系图,自动处理fixture重定义的覆盖逻辑,不需要自己编写解析代码。


内容的提问来源于stack exchange,提问作者decorator-factory

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 00:27:42