pytest运行失败时加--pdb参数可自动进入pdb调试器,停在异常抛出处;--trace用于逐行调试,--pdb-on-failure无效时可用assert false伪造失败触发pdb。

pytest运行时怎么触发pdb交互式调试
直接在命令行加 --pdb 参数,pytest会在测试失败时自动进入pdb;如果想在任意位置中断(比如还没报错但想查变量),用 --trace,它会在测试函数入口处就停下,等你手动输入 n 或 s 继续。
常见错误是只写 python -m pdb pytest test_x.py —— 这样pdb会去调试pytest这个命令本身,而不是你的测试逻辑,根本进不到测试函数里。
-
pytest test_math.py::test_add --pdb:仅对指定测试用例启用失败后断点 -
pytest test_math.py --trace:每个测试函数开头都暂停,适合排查初始化问题 - 配合
-s一起用(如--pdb -s),否则print输出会被捕获,你看不到实时日志
如何在测试代码里埋下pdb断点
Python 3.11 原生支持 breakpoint(),它比老式的 import pdb; pdb.set_trace() 更干净,且受 PYTHONBREAKPOINT 环境变量控制。在pytest中直接写 breakpoint() 就行,不需要额外导入。
注意:如果你在非主模块(比如 conftest.py 或 fixture 里)调用了 breakpoint(),得确保 pytest 没有通过 --capture=no 之外的方式屏蔽了 stdin/stdout,否则 pdb 提示符可能不显示或卡住。
- 在测试函数中间写
breakpoint(),运行pytest -s test_x.py就能停住 - 想临时禁用所有
breakpoint()?设环境变量PYTHONBREAKPOINT=0 - 想换成其他调试器(如ipdb)?设
PYTHONBREAKPOINT=ipdb.set_trace
pytest + pdb 调试时看不到局部变量怎么办
默认 pdb 的 p 命令不能直接打印未命名表达式(比如 p x + y 可能报 NameError),而且 pp 对嵌套结构也不总友好。更可靠的是用 !print(...) 或 pp locals()。
另一个常见现象:在fixture里断住后,l(list)命令显示的代码行数和你源文件对不上——这是因为pytest会包装测试函数,实际执行的是动态生成的闭包。此时别依赖行号,多用 u(up)和 d(down)切换帧,再用 ll(long list)看当前帧完整上下文。
- 查当前作用域所有变量:
pp locals() - 执行任意语句(包括调用函数):
!result = my_func(1, 2) - 跳到上一层调用帧(比如从fixture回到测试函数):
u - 避免卡在 pytest 内部帧:用
bt看调用栈,找准含test_或conftest的帧再u/d
为什么pdb在fixture里断住后无法继续执行
最典型的情况是用了 yield 的 fixture(比如带 teardown 清理的),你在 yield 前断住了,然后按 c(continue)——pdb 会直接跑到 yield 后、甚至 fixture 结束之后,导致测试函数根本没运行。这不是 bug,是 yield 机制和 pdb 单步逻辑叠加的结果。
本质是:pytest 在 fixture 执行完 yield 后才真正调用测试函数。所以你在 yield 前停住,c 会越过整个测试体,直接进 teardown 阶段。
- 对策一:改用
returnfixture,避开 yield,调试更线性 - 对策二:在测试函数内部设
breakpoint(),绕过 fixture 复杂流程 - 对策三:用
n(next)单步,而不是c(continue),逐行确认 yield 是否被触发 - 如果必须 debug yield fixture,优先在 yield 行设断点,再用
u切到测试函数帧检查状态
bt 看栈,再 u 找人。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











