pytest要求文件名以test_开头或_test结尾、函数名以test_开头、类名以test开头且无__init__方法,否则无法识别;assert需直接表达逻辑,避免bool()包装和浮点数直接比较。

直接上手 pytest 不需要写 main(),也不用继承类,只要文件名、函数名、断言写对,pytest 命令一敲就跑起来。
test_ 开头的文件和函数为什么必须这样命名
pytest 默认只扫描满足命名规则的文件和函数:文件名以 test_ 开头或 _test 结尾;函数名以 test_ 开头;类名以 Test 开头且不含 __init__ 方法。这不是风格建议,是发现机制硬约束。
常见错误现象:
- 写了
check_login(),但没加test_前缀 → pytest 完全忽略这个函数 - 文件叫
login.py→ pytest 不会加载它,哪怕里面全是test_函数 - 类里写了
def __init__(self):→ pytest 报错TypeError: Can't instantiate abstract class
实际使用中,推荐统一用 test_*.py 命名,避免结尾形式带来的路径歧义。类不是必须的,单个函数足够覆盖大多数单元测试场景。
assert 断言失败时怎么快速定位问题
pytest 的 assert 是增强版,失败时自动展开表达式、显示左右值,但前提是别绕弯子。
容易踩的坑:
- 写
assert bool(x) == True→ 实际应写assert x,否则报错信息里只显示False == True,丢失原始值 - 用
==比较浮点数(如assert 0.1 + 0.2 == 0.3)→ 因精度问题必然失败,改用assert abs((0.1 + 0.2) - 0.3) - 检查字符串包含关系写成
assert "abc" in data.text,但data.text是None→ 报AttributeError,不是断言失败,得先加assert data.text is not None
调试技巧:在 assert 后加自定义提示,比如 assert response.status_code == 200, f"Expected 200, got {response.status_code}",能立刻看到上下文。
如何运行单个测试函数或跳过某条用例
命令行控制粒度很细,不用改代码就能灵活执行。
常用操作:
- 运行整个文件:
pytest test_api.py - 运行某个函数:
pytest test_api.py::test_get_user - 运行某个类里的所有函数:
pytest test_api.py::TestClass - 跳过某条用例(临时禁用):
@pytest.mark.skip(reason="not ready")加在函数上方 - 条件跳过(比如只在 Linux 运行):
@pytest.mark.skipif("sys.platform != 'linux'", reason="Only runs on Linux")
注意:跳过标记不会导致测试失败,状态显示为 s(skipped),而 @pytest.mark.xfail 是预期失败,状态为 x,二者语义完全不同。
为什么不用写 setup/teardown 就能管理测试环境
因为 pytest 内置 fixture,比 unittest 的 setUp/tearDown 更轻量、更灵活。
最简实践:
- 定义一个带
@pytest.fixture的函数,比如db_connection,返回数据库连接对象 - 在测试函数参数里直接写同名变量名:
def test_query(db_connection):,pytest 自动注入 - 加
yield可做清理,比如yield conn; conn.close()
关键点:fixture 默认作用域是函数级(scope="function"),每次测试都新建;若想跨函数复用(如登录态),显式声明 scope="session",但要注意状态污染风险——这恰恰是新手最容易忽略的复杂点:看似省事的共享 fixture,可能让用例之间产生隐式依赖。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











