pytest默认只收集test_.py或_test.py文件,函数需以test_开头;tests/应与src/平级;conftest.py按目录层级就近生效;推荐使用原生assert提升错误可读性。

测试文件怎么命名才不会被pytest漏掉
pytest默认只收集以 test_ 开头或以 _test 结尾的 Python 文件。如果你写了 my_tests.py 或 check_login.py,它直接跳过——不是bug,是设计如此。
- 必须用
test_*.py(推荐)或*_test.py,比如test_user_auth.py、api_test.py - 模块内函数名也得是
test_开头,def test_login_success():可以,def verify_login():不会执行 - 如果非要用自定义命名,得在
pyproject.toml里显式配置:[tool.pytest.ini_options] python_files = ["check_*.py", "validate_*.py"]
但不建议,团队协作时容易遗忘或不一致
tests/ 目录放哪?和 src/ 平级还是嵌套在项目根目录
放在项目根目录下、与 src/ 平级最稳妥。很多新手把 tests/ 塞进 src/myapp/tests/,结果跑测试时 Python 路径混乱,ImportError: No module named 'myapp' 频发。
- 推荐结构:
myproject/ ├── pyproject.toml ├── src/ │ └── myapp/ │ ├── __init__.py │ └── auth.py └── tests/ ├── __init__.py └── test_auth.py - 这样配
pyproject.toml中的pythonpath = ["src"]就能确保测试代码 import 的是源码,不是已安装的包 - 如果用
setup.py或pip install -e .,也要确认src在packages配置里,否则pip安装后路径又对不上
如何让不同层级的 conftest.py 正确生效
conftest.py 的作用域取决于它所在目录:pytest 会从测试文件所在目录向上逐级查找,直到根目录,但**不会跨分支**。常见错误是把全局 fixture 写在 tests/conftest.py,却在 tests/integration/conftest.py 里重定义同名 fixture,结果后者覆盖前者,且没报错。
- 层级优先级:测试文件所在目录 > 上一级目录 > 再上一级…… > 项目根目录(只要在测试路径内)
- 想复用 fixture,用
autouse=True要谨慎:tests/conftest.py里的@pytest.fixture(autouse=True)会影响所有子目录测试,但tests/unit/conftest.py里的同名 fixture 会完全屏蔽父级的 - 跨目录共享 fixture 的安全做法:在
tests/conftest.py中用from pytest import fixture显式导入并重新声明,而不是依赖自动发现
为什么 pytest --tb=short 还是看到一屏红色堆栈
因为 --tb=short 只缩短 traceback 深度,并不隐藏断言失败详情。真正影响可读性的是断言本身是否“可读”——pytest 默认对 assert a == b 做了增强,但一旦套了函数调用或用了 assertTrue() 这类 unittest 风格写法,就退化成原始 Python 报错。
- 坚持用原生
assert:assert response.status_code == 200,别写self.assertEqual(response.status_code, 200) - 复杂比较加自定义消息:
assert len(users) == 3, f"expected 3 users, got {len(users)}" - 检查是否误启用了其他插件(比如
pytest-asyncio未正确标记 async 测试),会导致异常捕获逻辑错乱,堆栈变长
测试目录结构本身不难搭,难的是每次新增模块时,能否让新同事不用查文档就知道该把 test_xxx.py 放哪、该改哪个 conftest.py、为什么 import 突然报错——这些细节藏在第一次 pytest 执行失败的那几行提示里,而不是文档开头。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











