Python 编程:从零基础到精通
第 40 课 - 使用 pytest 进行测试
模块九:测试与调试
难度:中级 | 标签:testing, pytest
1. 学习目标
完成本课后,你将能够:
- 理解
pytest框架的优势,并能独立安装。 - 编写符合
pytest规范的、简单的测试函数。 - 使用
fixture来管理测试的前置条件和资源。 - 运行测试并解读测试结果。
2. 核心概念
上一课我们学习了 Python 内置的 unittest 模块。它强大且结构严谨,但对于新手来说,编写测试的"样板代码"较多。pytest 是一个更现代、更流行的第三方测试框架,它以其简洁的语法和强大的功能,大大提升了编写测试的效率和体验。
为什么选择 pytest?
- 更简洁的语法:你只需写一个以
test_开头的普通 Python 函数,然后使用 Python 内置的assert语句进行验证,无需继承任何类或学习特殊的断言方法。 - 自动发现:
pytest会自动发现并运行目录下所有符合命名规则的测试文件和测试函数。 - 强大的 Fixture 系统:这是
pytest最核心的特性之一。它允许你定义可复用的"测试资源"(如创建数据库连接、准备测试数据等),并在多个测试中灵活共享。 - 详尽的测试报告:失败时,它会清晰地展示变量的具体值,帮助你快速定位问题。
安装 pytest
pip install pytest
3. 代码示例
假设我们有一个待测试的模块 calculator.py,其中包含一个简单的加法函数。
calculator.py (待测试的代码)
def add(a, b):
"""返回两个数的和。"""
return a + b
test_calculator.py (测试文件)
import pytest
from calculator import add
# 测试函数 1:测试加法的基本功能
def test_add_positive_numbers():
"""测试正数相加。"""
assert add(2, 3) == 5
assert add(10, 20) == 30
# 测试函数 2:测试包含负数的加法
def test_add_negative_numbers():
"""测试负数相加。"""
assert add(-1, -1) == -2
assert add(-5, 5) == 0
# 测试函数 3:故意让测试失败,观察 pytest 的输出
def test_add_fail_example():
"""演示测试失败的情况。"""
result = add(2, 3)
# 我们故意写错期望值,让这个测试失败
assert result == 6 # 这里会失败,因为 2 + 3 不等于 6
运行测试
在终端中,进入 test_calculator.py 所在的目录,执行:
pytest test_calculator.py -v
-v 选项(verbose)会显示更详细的输出。
4. 实践练习
练习 1:基础测试
创建一个函数 multiply(a, b),用于计算两个数的乘积。为它编写至少 3 个测试用例(例如:正数相乘、负数相乘、与零相乘),并确保全部通过。
练习 2:使用 Fixture
假设你需要测试一个用户注册功能。在测试之前,需要创建一个临时的测试数据库连接;在测试完成后,需要关闭连接。请使用 pytest 的 fixture 来编写一个 db_connection 的 fixture,并编写一个测试函数 test_user_registration 来使用它。
练习 3:高级测试运行 使用上一个练习的代码,尝试运行以下命令并解释其作用:
pytest -k "registration"
pytest -k "not multiplication"
5. 常见错误
- 忘记导入:在测试文件中忘记
import你要测试的模块或函数,导致NameError。 - 测试文件/函数命名错误:
- 测试文件必须命名为
test_*.py或*_test.py。 - 测试函数必须以
test_开头。
- 测试文件必须命名为
- 滥用
assert:assert是一个语句,不是函数。不要写成assert(x == y),虽然这在大多数情况下也能工作,但写成assert x == y是更符合习惯的用法,并且pytest能提供更详细的错误信息。 - Fixture 作用域 (Scope) 混淆:
fixture的scope参数(function,class,module,session)决定了fixture的实例创建和销毁频率。初学者常将需要为每个测试重新创建的fixture错误地设置为module或session级别,导致测试之间产生相互干扰。
6. 小结
本课我们学习了使用 pytest 框架进行测试的核心要点:
- 安装与优势:通过
pip install pytest安装,它以简洁的语法和自动发现机制优于unittest。 - 编写测试:创建
test_*.py文件,定义test_开头的函数,使用assert进行验证。 - 运行测试:在终端使用
pytest命令,配合-v等选项查看详细报告。 - Fixture:理解了
fixture的概念,它用于管理测试的前置和后置条件,是pytest复用代码和资源管理的强大工具。
掌握 pytest 是现代 Python 开发者的必备技能。下一课,我们将学习如何使用 mock 来模拟外部依赖,进行更独立、更高效的测试。