以下教程将引导你快速学习 Python 测试,掌握基础工具和技术,以覆盖 80% 的常见场景。
1. 基础测试示例:简单函数
编写测试的目的是验证函数在各种输入情况下的正确性。
# 功能函数:实现两个数的加法
def add(x, y):
"""
简单的加法函数
:param x: 加数1
:param y: 加数2
:return: 两数相加的结果
"""
return x + y
# 测试函数:验证 add 函数的正确性
def test_add():
"""
测试 add 函数,覆盖常见场景
"""
# 正常情况下
assert add(2, 3) == 5 # 2+3 应该等于 5
# 边界值情况
assert add(-1, 1) == 0 # -1+1 应该等于 0
# 特殊值情况
assert add(0, 0) == 0 # 0+0 应该等于 0
运行测试
在命令行中运行:
pytest test_example.py
输出说明:
.
表示通过的测试F
表示失败的测试
2. 参数化测试:减少重复代码
参数化测试可以一次性覆盖多个测试用例。
import pytest
# 功能函数:实现加法
def add(x, y):
return x + y
# 测试函数:使用参数化装饰器简化多案例测试
@pytest.mark.parametrize("x, y, expected", [
(2, 3, 5), # 正常值
(-1, 1, 0), # 边界值
(0, 0, 0), # 特殊值
(100, 200, 300), # 较大值
])
def test_add(x, y, expected):
"""
测试加法函数,覆盖多种输入情况
"""
assert add(x, y) == expected
优点:
- 避免重复编写
assert
。 - 新增测试用例只需添加参数。
3. 测试异常:验证错误处理逻辑
异常测试用来确保代码在错误输入时能正确抛出错误。
# 功能函数:实现除法,并处理除零情况
def divide(x, y):
"""
简单除法函数,处理除以零的特殊情况
:param x: 被除数
:param y: 除数
:return: 商
:raises ValueError: 如果 y 为 0
"""
if y == 0:
raise ValueError("Cannot divide by zero") # 抛出异常
return x / y
# 测试函数:验证 divide 的错误处理逻辑
def test_divide():
"""
测试 divide 函数,确保异常正确抛出
"""
# 正常情况
assert divide(10, 2) == 5 # 10/2 应该等于 5
# 测试异常:除以零
with pytest.raises(ValueError, match="Cannot divide by zero"):
divide(1, 0) # 应该抛出 ValueError
关键点:
- 使用
pytest.raises
检查异常是否抛出。 match
参数验证异常信息是否正确。
4. 测试类和方法
面向对象代码中,你需要测试类的初始化和方法行为。
# 功能类:实现简单的计算器
class Calculator:
"""
一个简单的计算器类,用于累积计算
"""
def __init__(self):
self.result = 0 # 初始化结果为 0
def add(self, value):
"""
将 value 加到当前结果中
:param value: 要添加的值
"""
self.result += value
def subtract(self, value):
"""
从当前结果中减去 value
:param value: 要减去的值
"""
self.result -= value
# 测试类:验证 Calculator 的行为
def test_calculator():
"""
测试 Calculator 类的功能
"""
calc = Calculator() # 初始化计算器
calc.add(10) # 加 10
assert calc.result == 10 # 当前结果应该为 10
calc.subtract(5) # 减去 5
assert calc.result == 5 # 当前结果应该为 5
5. 使用 Fixtures:复用测试准备代码
pytest
提供 fixture
来简化测试中重复的准备工作。
import pytest
# 功能函数:简单用户数据验证
def validate_user(user):
"""
验证用户数据是否完整
:param user: 字典类型,包含用户数据
:return: 是否有效
"""
return "name" in user and "email" in user
# Fixture:提供测试数据
@pytest.fixture
def user_data():
"""
返回测试用的用户数据
"""
return {"name": "Alice", "email": "alice@example.com"}
# 测试函数:使用 fixture 提供的数据
def test_validate_user(user_data):
"""
测试 validate_user 函数
"""
assert validate_user(user_data) # 数据应通过验证
# 修改数据,验证失败情况
user_data.pop("email")
assert not validate_user(user_data) # 数据不应通过验证
优点:
- 提供共享数据,减少重复代码。
- 提高代码可读性和可维护性。
6. Mock 测试:模拟外部依赖
通过 unittest.mock
模块模拟外部依赖的行为。
from unittest.mock import MagicMock
# 功能函数:从 API 获取数据
def get_data_from_api(api_client):
"""
从 API 客户端获取数据
:param api_client: API 客户端对象
:return: 获取的数据
"""
return api_client.fetch_data()
# 测试函数:模拟 API 行为
def test_get_data_from_api():
"""
测试 get_data_from_api 函数
"""
# 模拟 API 客户端
mock_client = MagicMock()
mock_client.fetch_data.return_value = {"data": "mocked data"} # 模拟返回值
# 调用函数,验证返回结果
result = get_data_from_api(mock_client)
assert result == {"data": "mocked data"} # 应该返回模拟数据
# 验证 fetch_data 是否被正确调用
mock_client.fetch_data.assert_called_once()
7. 覆盖报告
测试代码完成后,建议生成代码覆盖率报告:
-
安装工具:
pip install pytest-cov
-
运行测试并生成覆盖率报告:
pytest --cov=your_module test_example.py
-
生成 HTML 报告:
pytest --cov=your_module --cov-report=html
-
查看 HTML 报告:
打开生成的
htmlcov/index.html
。