pytest要求测试函数以test_开头、文件名符合test_.py或_test.py、类名为test*且无__init__方法,assert必须含具体检查逻辑,异常需用pytest.raises断言,边界值和fixture/parametrize应显式覆盖。

Pytest 本身不强制要求特定结构,但写错 test_ 命名或漏掉 assert 就根本不会运行或判为通过——这不是“没测”,是“假装测了”。
为什么 pytest 找不到你的测试函数?
Pytest 默认只识别以 test_ 开头的函数(或以 _test 结尾),且必须在 test_*.py 或 *_test.py 文件里。类名也得是 Test* 形式,且不能带 __init__ 方法。
- 错误示例:
def check_add():→ 不会被发现 - 正确写法:
def test_add_two_numbers(): - 文件名必须是
test_math.py或math_test.py,不能叫math_tests.py(多一个 s 就失效) - 如果用了类,
class TestCalculator:可以,但class CalculatorTests:不行
assert 之后不写具体检查逻辑,等于没测
常见写法 assert my_func(1, 2) 看似简洁,实则危险:只要返回真值(比如非空字符串、非零数、非 None)就通过,哪怕结果是错的。
- 错:
assert add(2, 3)→add返回 5 时通过,返回 "5" 或 True 也通过 - 对:
assert add(2, 3) == 5 - 更稳:
assert isinstance(add(2, 3), int) and add(2, 3) == 5 - 报错信息更清晰时用
assert ... , "描述性失败消息",比如assert result > 0, "should return positive number"
如何让测试覆盖边界和异常场景?
只测“正常输入”会掩盖大量潜在问题。Pytest 对异常断言支持直接,但必须显式声明预期行为。
- 期望抛异常:
with pytest.raises(ValueError): parse_int("abc") - 注意:不能写
assert parse_int("abc") raises ValueError—— 这语法错误 - 边界值要单独列:比如输入
0、None、空列表、极大数,别指望“顺带测到” - 避免在测试里用
try/except捕获异常再 assert,pytest 的raises更精准、可追踪堆栈
fixture 和参数化怎么避免重复代码?
重复 setup/teardown 逻辑(如创建临时文件、初始化数据库连接)该用 @pytest.fixture;相同逻辑跑多组输入该用 @pytest.mark.parametrize。
- fixture 示例:
@pytest.fixture def temp_db():里创建并 yield 一个 db 实例,测试函数直接当参数接收 - 参数化示例:
@pytest.mark.parametrize("a,b,expected", [(1,2,3), (0,0,0), (-1,1,0)]),函数签名写def test_add(a, b, expected): - 坑点:fixture 默认作用域是函数级,若需跨测试复用(如共享 DB 连接),加
scope="session",但得小心状态污染 - 参数化时,如果某组数据预期失败,用
pytest.param(..., marks=pytest.mark.xfail)显式标记
最常被跳过的其实是“测试自己改的那行代码是否真被覆盖到了”——别信直觉,加一句 print() 或跑一次 pytest --cov=my_module 看报告,否则你写的测试很可能只在验证函数存在,而不是逻辑正确。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











