40·模块九:测试与调试进阶

使用 pytest 进行测试

testingpytest

Python 编程:从零基础到精通

第 40 课 - 使用 pytest 进行测试

模块九:测试与调试

难度:中级 | 标签:testing, pytest


1. 学习目标

完成本课后,你将能够:

  1. 理解 pytest 框架的优势,并能独立安装。
  2. 编写符合 pytest 规范的、简单的测试函数。
  3. 使用 fixture 来管理测试的前置条件和资源。
  4. 运行测试并解读测试结果。

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 假设你需要测试一个用户注册功能。在测试之前,需要创建一个临时的测试数据库连接;在测试完成后,需要关闭连接。请使用 pytestfixture 来编写一个 db_connection 的 fixture,并编写一个测试函数 test_user_registration 来使用它。

练习 3:高级测试运行 使用上一个练习的代码,尝试运行以下命令并解释其作用:

pytest -k "registration"
pytest -k "not multiplication"

5. 常见错误

  1. 忘记导入:在测试文件中忘记 import 你要测试的模块或函数,导致 NameError
  2. 测试文件/函数命名错误
    • 测试文件必须命名为 test_*.py*_test.py
    • 测试函数必须以 test_ 开头。
  3. 滥用 assertassert 是一个语句,不是函数。不要写成 assert(x == y),虽然这在大多数情况下也能工作,但写成 assert x == y 是更符合习惯的用法,并且 pytest 能提供更详细的错误信息。
  4. Fixture 作用域 (Scope) 混淆fixturescope 参数(function, class, module, session)决定了 fixture 的实例创建和销毁频率。初学者常将需要为每个测试重新创建的 fixture 错误地设置为 modulesession 级别,导致测试之间产生相互干扰。

6. 小结

本课我们学习了使用 pytest 框架进行测试的核心要点:

  • 安装与优势:通过 pip install pytest 安装,它以简洁的语法和自动发现机制优于 unittest
  • 编写测试:创建 test_*.py 文件,定义 test_ 开头的函数,使用 assert 进行验证。
  • 运行测试:在终端使用 pytest 命令,配合 -v 等选项查看详细报告。
  • Fixture:理解了 fixture 的概念,它用于管理测试的前置和后置条件,是 pytest 复用代码和资源管理的强大工具。

掌握 pytest 是现代 Python 开发者的必备技能。下一课,我们将学习如何使用 mock 来模拟外部依赖,进行更独立、更高效的测试。

练习编辑器

python
Loading...

继续学习

完成本课后,建议继续学习下一课「Mock 测试与模拟对象」 以巩固所学知识。