pytest-mypy插件已弃用,因其依赖过时的pytest钩子和mypy CLI接口,不兼容现代工具链;推荐使用活跃维护的pytest-run-mypy替代,支持pyproject.toml配置、标准错误输出及完整源码扫描。

直接在 pytest 运行时触发 mypy 类型检查是可行的,但 pytest-mypy 插件本身**早已被弃用且不兼容现代 pytest 和 mypy**——它最后一次发布是 2019 年,无法处理 pyproject.toml 配置、mypy 1.0+ 的 API 变更,甚至会在 pytest 7+ 中报 ValueError: unknown hook 'pytest_mypy' 错误。
为什么不能直接用 pytest-mypy 插件
该插件依赖已移除的 pytest 钩子机制,且硬编码调用旧版 mypy CLI 接口。实际测试中会遇到:
ImportError: cannot import name 'MypyItem' from 'pytest_mypy'- 类型检查结果不显示具体错误行号,或完全静默失败
- 与
mypy --follow-imports=normal行为冲突,导致模块未被扫描 - 无法识别
pyproject.toml中的[tool.mypy]配置
推荐方案:用 pytest-run-mypy 替代
pytest-run-mypy 是当前活跃维护的替代品(截至 2024 年最新版 0.10.0),它通过标准 pytest hook 注册一个独立的 test item,真正把 mypy 执行包装成 pytest 测试用例。
安装与基本用法:
立即学习“Python免费学习笔记(深入)”;
pip install pytest-run-mypy
运行命令:
pytest --mypy
关键行为说明:
- 默认只检查
test_*.py和*_test.py文件中 import 的源码模块(即测试所依赖的代码) - 若要检查全部源码(如
src/下所有.py),需显式指定路径:pytest --mypy src/ - 支持
pyproject.toml中的[tool.mypy]配置,无需额外参数 - 失败时输出标准 mypy 格式错误(含文件、行号、错误码),并让 pytest 整体返回非零退出码
如何避免“类型检查不生效”的典型陷阱
常见失效场景不是插件问题,而是配置或路径理解偏差:
- 没在项目根目录运行
pytest --mypy,导致 mypy 找不到pyproject.toml配置 - 源码在
src/目录但只运行pytest --mypy(不带路径),此时它只检查测试文件本身,不扫描src/ -
pyproject.toml中[tool.mypy]写成了[mypy]或[tool.pytest],mypy 完全不读取 - 测试文件里用了
from mypackage import *,但 mypy 默认不检查 stubs 或动态导入模块——需加disallow_untyped_defs = true等显式规则才能暴露问题
最易被忽略的一点:mypy 检查的是 import 后实际加载的模块路径,不是文件路径。如果测试里写 from src.mymodule import func,但项目没设 src 为 root package(比如没在 pyproject.toml 里配 packages = [{include = "src"}] 或没建 src/__init__.py),mypy 就会跳过该模块——不是插件问题,是 Python 导入系统和 mypy 的路径解析逻辑共同导致的。


















