pytest 测试框架入门:从零跑通第一个测试
【免费下载链接】pytestThe pytest framework makes it easy to write small tests, yet scales to support complex functional testing项目地址: https://gitcode.com/GitHub_Trending/py/pytest
pytest 是 Python 生态里最常用的测试框架:一条命令完成测试收集、执行和结果输出,断言直接写 assert,不需要记住一堆 API。
为什么选它
- 写测试像写普通代码:断言就是
assert,不用self.assertEqual,测试函数不必继承 TestCase。 - 收集规则省心:文件命名
test_*.py、函数命名test_*即被自动发现,不用手动注册。 - 失败信息可读:assert 表达式经过 AST 重写,报错时打印左右两边实际值,不用自己 print 调试。
- fixture 管理资源:数据库连接、临时文件等前后置逻辑声明一次,多个测试复用。
- 插件生态成熟:覆盖率、并行执行、mock 打桩等常见需求都有对应插件。
5 分钟跑通
pip 安装 pytest
在终端执行安装命令,支持 Python 3.8+ 和 PyPy3:
pip install pytest写一个最小测试
新建test_demo.py,内容只有一个函数,注意文件名和函数名都要符合test_前缀约定:
def test_answer(): assert 1 + 1 == 2运行并查看输出
在项目根目录直接敲pytest:
pytest test_demo.py看到类似下面的输出,说明环境没问题:
===================== test session starts ===================== collected 1 item test_demo.py . [100%] ======================= 1 passed in 0.01s ======================测试失败时,pytest 会打印断言处左右两侧的实际值,定位错误不用再写 print。
一个完整场景
场景:给小工具函数补测试
你写了一个计算器模块,包含add和divide两个函数。问题在于:divide除数为 0 时会抛异常,普通断言覆盖不到;add想验证多组输入,又不想把三行断言复制粘贴三遍。
思路是用@pytest.mark.parametrize给add灌入多组参数,用@pytest.raises捕获divide的异常,再配一个 fixture 提供公共测试数据。
calculator.py是被测代码:
def add(a, b): return a + b def divide(a, b): if b == 0: raise ValueError("除数不能为 0") return a / btest_calculator.py写对应的测试,参数化把多组用例压缩进一个装饰器:
import pytest from calculator import add, divide @pytest.fixture def sample_numbers(): return (2, 3) @pytest.mark.parametrize("a, b, expected", [ (1, 2, 3), (0, 5, 5), (-1, 1, 0), ]) def test_add(a, b, expected): assert add(a, b) == expected def test_divide_by_zero(sample_numbers): with pytest.raises(ValueError): divide(*sample_numbers, 0)运行pytest test_calculator.py -v,4 条用例全部通过,参数化展开后每条一目了然:
test_add[1-2-3] PASSED test_add[0-5-5] PASSED test_add[-1-1-0] PASSED test_divide_by_zero PASSED之后新增用例,只需在 parametrize 列表里加一行,测试函数本身不用动。
实用技巧与常见坑
- 命名不对就静默收集不到:只有
test_*.py或*_test.py文件、test_*前缀的函数会被发现,写成tests.py或check_xxx时 pytest 不报错,只是跑了 0 条用例,容易误判。 - 别写恒真断言:
assert True、if x != y: raise这类写法拿不到 pytest 重写的 diff 信息,直接写真实表达式。 - fixture 清理记得用 yield:
yield前后分别对应 setup/teardown,漏写 teardown 会让临时文件越积越多;fixture 默认 scope 是 function,每条测试都会重新执行一遍。 - 用
-k快速筛测试:pytest -k "add and not zero"按名称表达式过滤,改完单个函数时比跑全量快很多。 .pytest_cache加进 .gitignore:pytest 会写缓存记录上次失败的位置,提交到仓库会污染 diff。
扩展生态速览
- pytest-cov:结合 coverage 输出行覆盖率报告,
--cov一个参数搞定。 - pytest-mock:fixture 里拿到
mocker对象,直接 patch 函数、方法和属性。 - pytest-xdist:
pytest -n auto把测试分到多进程并行执行,适合大规模套件。 - pytest-django:为 Django 项目提供数据库事务回滚和管理命令测试。
- pytest-rerunfailures:对不稳定的测试自动重跑,并单独标记出 flaky 用例。
【免费下载链接】pytestThe pytest framework makes it easy to write small tests, yet scales to support complex functional testing项目地址: https://gitcode.com/GitHub_Trending/py/pytest
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考