Pytest斷言的使用:驗證執行結果是否正確
前言
在 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 中常用的斷言方法,并通過具體的示例代碼展示了它們的使用方法:
基本斷言:驗證函數的返回值。
多重斷言:驗證多個條件。
斷言異常:驗證函數是否會拋出特定的異常。
斷言特定異常消息:驗證拋出的異常是否包含特定的消息。
斷言列表和字典:驗證數據結構是否符合預期。
斷言浮點數:驗證浮點數是否近似相等。
斷言字符串:驗證字符串是否包含特定的子串。
斷言元組:驗證元組是否符合預期。
斷言列表和字典的子集:驗證列表或字典的子集。
斷言日志:驗證日志輸出。