前言
在 pytest 中,断言(assertion)是测试用例中最核心的部分之一。断言用于验证函数或方法的执行结果是否符合预期。正确的断言不仅能够帮助我们发现错误,还能提供详细的错误信息,便于快速定位问题。
1. 基本断言
1.1 示例代码
假设我们有一个简单的函数 add,我们想要编写一个测试用例来验证这个函数的行为。
# 文件名:mylib.py
def add(a, b):
return a + b
接下来,我们编写一个测试用例来验证 add 函数。
# 文件名:test_mylib.py
def test_add():
assert add(1, 2) == 3
assert add(-1, 1) == 0
assert add(0, 0) == 0
2. 多重断言
有时候我们需要在一个测试用例中验证多个条件。可以使用多个 assert 语句来实现这一点。
2.1 示例代码
# 文件名:test_mylib.py
def test_add_multiple_conditions():
assert add(1, 2) == 3
assert add(-1, 1) == 0
assert add(0, 0) == 0
assert add(100, 200) == 300
3. 断言异常
有时我们需要验证函数是否会抛出特定的异常。可以使用 with pytest.raises() 上下文管理器来实现这一点。
3.1 示例代码
假设我们有一个函数 divide,它可能会抛出 ZeroDivisionError。
# 文件名:mylib.py
def divide(a, b):
return a / b
接下来,我们编写一个测试用例来验证 divide 函数是否会抛出异常。
# 文件名:test_mylib.py
def test_divide_zero():
with pytest.raises(ZeroDivisionError):
divide(1, 0)
4. 断言特定异常消息
有时我们需要验证抛出的异常是否包含特定的消息。可以使用 match 参数来实现这一点。
4.1 示例代码
# 文件名:test_mylib.py
def test_divide_zero_message():
with pytest.raises(ZeroDivisionError, match="division by zero"):
divide(1, 0)
5. 断言列表和字典
在验证数据结构时,经常需要断言列表或字典是否符合预期。
5.1 示例代码
假设我们有一个函数 process_data,它返回一个列表。
# 文件名:mylib.py
def process_data():
return [1, 2, 3]
接下来,我们编写一个测试用例来验证 process_data 函数的返回值。
# 文件名:test_mylib.py
def test_process_data():
assert process_data() == [1, 2, 3]
5.2 断言字典
假设我们有一个函数 get_user_info,它返回一个字典。
# 文件名:mylib.py
def get_user_info():
return {"name": "Alice", "age": 25}
接下来,我们编写一个测试用例来验证 get_user_info 函数的返回值。
# 文件名:test_mylib.py
def test_get_user_info():
assert get_user_info() == {"name": "Alice", "age": 25}
6. 断言浮点数
在处理浮点数时,由于浮点数的精度问题,直接使用 == 可能会导致误判。可以使用 pytest.approx 来实现这一点。
6.1 示例代码
假设我们有一个函数 calculate_pi,它返回一个近似值。
# 文件名:mylib.py
def calculate_pi():
return 3.14159265358979323846
接下来,我们编写一个测试用例来验证 calculate_pi 函数的返回值。
# 文件名:test_mylib.py
def test_calculate_pi():
assert calculate_pi() == pytest.approx(3.141592653589793, abs=1e-10)
7. 断言字符串
在验证字符串时,可以使用 assert 来检查字符串是否包含特定的子串。
7.1 示例代码
假设我们有一个函数 greet,它返回一个问候字符串。
# 文件名:mylib.py
def greet(name):
return f"Hello, {name}!"
接下来,我们编写一个测试用例来验证 greet 函数的返回值。
# 文件名:test_mylib.py
def test_greet():
assert "Hello, Alice!" == greet("Alice")
assert "Hello, Bob!" == greet("Bob")
8. 断言元组
在验证元组时,可以使用 assert 来检查元组是否符合预期。
8.1 示例代码
假设我们有一个函数 get_coordinates,它返回一个坐标元组。
# 文件名:mylib.py
def get_coordinates():
return (1.0, 2.0)
接下来,我们编写一个测试用例来验证 get_coordinates 函数的返回值。
# 文件名:test_mylib.py
def test_get_coordinates():
assert get_coordinates() == (1.0, 2.0)
9. 断言列表和字典的子集
在验证列表或字典的子集时,可以使用 Python 的内置函数 all 或 any 来实现这一点。
9.1 示例代码
假设我们有一个函数 get_students,它返回一个学生列表。
# 文件名:mylib.py
def get_students():
return [{"name": "Alice", "age": 25}, {"name": "Bob", "age": 30}]
接下来,我们编写一个测试用例来验证 get_students 函数的返回值。
# 文件名:test_mylib.py
def test_get_students():
students = get_students()
assert all(student["age"] >= 18 for student in students)
assert any(student["name"] == "Alice" for student in students)
10. 断言日志
在验证日志输出时,可以使用 caplog 固定夹(fixture)来捕获日志输出。
10.1 示例代码
假设我们有一个函数 log_error,它记录一条错误日志。
# 文件名:mylib.py
import logging
logger = logging.getLogger(__name__)
def log_error(message):
logger.error(message)
接下来,我们编写一个测试用例来验证 log_error 函数的日志输出。
# 文件名:test_mylib.py
import logging
import pytest
def test_log_error(caplog):
caplog.set_level(logging.ERROR)
log_error("An error occurred")
assert "An error occurred" in caplog.text
11. 总结
通过以上示例,我们详细介绍了 pytest 中常用的断言方法,并通过具体的示例代码展示了它们的使用方法:
基本断言:验证函数的返回值。
多重断言:验证多个条件。
断言异常:验证函数是否会抛出特定的异常。
断言特定异常消息:验证抛出的异常是否包含特定的消息。
断言列表和字典:验证数据结构是否符合预期。
断言浮点数:验证浮点数是否近似相等。
断言字符串:验证字符串是否包含特定的子串。
断言元组:验证元组是否符合预期。
断言列表和字典的子集:验证列表或字典的子集。
断言日志:验证日志输出。