vscode调试单元测试断点不触发的核心原因是工作目录、导入路径与pytest执行流未对齐;需确保cwd设为src、sys.path包含模块路径,并确认pytest正确加载测试文件而非被当作普通python文件运行。

VSCode 调试单元测试不是“点开就断”,核心卡点在工作目录、导入路径和测试框架执行流三者是否对齐;断点打在 test_* 函数里却跳过,大概率是 pytest 没真正加载你的模块,而非调试器失灵。
为什么 test_*.py 里的断点不触发
断点不触发的常见现象:点击「Debug Test」后控制台快速刷完、无暂停、变量面板为空。这不是 VSCode 坏了,而是调试器压根没进入你写的测试逻辑。
-
pytest启动时默认使用自己的 import 机制,若src/不在sys.path中,from src.mymodule import func会静默失败或 fallback 到错误路径 - 断点只能生效于 pytest 实际执行的代码段——比如
def test_something():函数体内、fixture 调用之后;打在conftest.py的 fixture 定义行上,不会停(除非加--capture=no -s并启用pytest-pdb) - 如果测试文件本身被识别为普通 Python 文件(而非测试文件),VSCode 可能根本没调用
pytest,而是用python -m unittest或直接运行,导致路径逻辑完全不同
如何让 cwd 和 sys.path 对齐
VSCode 默认以打开的文件夹为工作目录(cwd),但你的模块结构可能要求从 src/ 下导入。不显式声明,pytest 就找不到 src.mymodule。
- 在
.vscode/settings.json中加:"python.testing.cwd": "src"
——这是最直接的做法,告诉测试框架“请把 src 当作根来跑” - 更通用的方式是注入
PYTHONPATH:"python.defaultEnvironment": {"PYTHONPATH": "${workspaceFolder}/src"}(注意:该字段非官方标准,部分 VSCode 版本需配合python.envFile使用) - 临时验证方法:在测试文件顶部加
import sys; print(sys.path),运行时看输出里有没有你期望的路径(如/path/to/project/src)
launch.json 配置要不要写
多数情况下不用手动写 launch.json——VSCode 的「Debug Test」按钮本质是封装好的命令行调用(如 pytest --debug --tb=short test_example.py::test_something)。只有当你需要精细控制参数时才需介入。
- 需要改
launch.json的典型场景:--runInBand(禁用 pytest 多进程)、--log-cli-level=INFO(查看日志)、或指定特定pytest.ini配置文件 - 如果写了
launch.json却发现断点失效,先检查type是否为"python",且module字段是否设为"pytest"(而不是留空或填错) - 不要在
launch.json里硬编码program指向某个.py文件——这会让 VSCode 绕过测试框架,直接用 Python 解释器执行,失去 pytest 的 fixture、参数化等能力
断点位置和作用域的隐蔽陷阱
你以为断点打对了,其实它根本不在执行路径上。尤其在参数化测试、fixture 依赖或异步测试中,断点容易落空。
- 参数化测试(
@pytest.mark.parametrize)中,断点要打在实际被调用的测试函数体内部,而不是装饰器行或参数列表行 - fixture 返回的是懒加载对象(如数据库 session)?断点打在
session.query(...)上才有效;打在session = get_session()这一行,只停在 fixture 初始化,不等于进了业务逻辑 - 异步测试(
async def test_xxx())必须确保运行器支持 asyncio——默认 pytest 不处理async,需装pytest-asyncio并加@pytest.mark.asyncio,否则断点所在协程根本不会被调度
最易被忽略的一点:VSCode 的测试资源管理器(Test Explorer)和编辑器内「Debug Test」按钮可能使用不同配置源。改完 settings.json 后,务必关闭再重开测试资源管理器,否则缓存的旧 cwd 仍生效。











