Maya 改了總價公式,得確認那張 18.75 的訂單還沒被改壞。一條 assert 一秒就能回答。什麼時候 assert 是錯的工具?
assert 語句會檢查一個條件,條件為假時拋出 AssertionError。學習階段,它是記錄並驗證預期的緊湊方式。它適合內部檢查和測試,不適合驗證不可信的使用者輸入。 你還會用表格驅動用例、斷言預期例外,並用容差比較浮點數。
斷言一個事實
assert add(2, 3) == 5 用可執行的形式寫出預期結果。如果函式以後改成回傳 6,程式會停在這一行。逗號後面的短訊息可以說明哪裡不符合預期。
def add(a, b):
return a + b
assert add(2, 3) == 5
print("ok")一個通過的檢查
測試多個例子
少量斷言就能覆蓋正常輸入和一個邊界情況。最重要的行為放在前面。某個斷言失敗時,Python 會報告行號並停止目前測試,後面的檢查不會執行。
def slugify(text):
return text.strip().lower().replace(" ", "-")
assert slugify(" Hello World ") == "hello-world"
assert slugify("Python") == "python"
print("2 tests passed")不止一個例子
捕獲失敗並查看原因
AssertionError 和其他例外一樣。在小範例裡捕獲它,可以只列印訊息而不顯示整段 traceback。真實測試套件中應讓測試執行器報告失敗,而不是把失敗藏起來。
def double(n):
return n * 2
try:
assert double(3) == 7, "double(3) should be 6"
except AssertionError as error:
print(error)讀取失敗訊息
把用例放進表格
用 (輸入, 預期) 列表把覆蓋範圍擺出來,每條斷言也能保持短小。訊息裡用 repr(),失敗時能看見準確的值。第一條失敗的 assert 會停止執行,所以測試執行器一次只報告一個失敗。
def slugify(text):
return text.strip().lower().replace(" ", "-")
cases = [(" Hello World ", "hello-world"), ("Python", "python"), ("", "")]
for raw, expected in cases:
actual = slugify(raw)
assert actual == expected, f"{raw!r}: {actual!r} != {expected!r}"
print(len(cases), "cases passed")一張表,一條清楚的失敗訊息
斷言例外,而不是保持沉默
有些行為本來就應該報錯。呼叫函式,只捕獲預期例外,並斷言它確實發生;else 分支負責抓「沒有報錯」的情況。真實測試套件裡用 pytest.raises 或 unittest 的 assertRaises,不要用裸 try 把失敗藏起來。
def parse_age(raw):
value = int(raw)
if value < 0:
raise ValueError("age must be non-negative")
return value
for raw in ["-1", "many"]:
try:
parse_age(raw)
except ValueError as error:
print(raw, type(error).__name__, error)
else:
print("no error", raw)預期失敗也是契約的一部分
浮點數用容差比較
二進位浮點會讓 0.1 + 0.2 與 0.3 略有差異。要求精確相等的測試測的是表示方式,不是目標值。用 math.isclose 並寫明容差;金額場景則比較整數分。
import math
total = 0.1 + 0.2
print(total == 0.3)
print(math.isclose(total, 0.3, rel_tol=1e-9))
assert math.isclose(total, 0.3, rel_tol=1e-9)
print("close enough")在規定容差內測試值
本課要點
- assert condition 在條件為假時拋出 AssertionError。
- 逗號後面的字串可以補充說明預期。
- 斷言用於測試和內部不變數,不用於使用者輸入驗證。
- Python 的 -O 參數會移除 assert,所以不能用它做安全驗證。
- 測試要有可見用例、明確的預期例外,以及對浮點數的容差。
常見錯誤
- 用 assert 驗證表單或密碼。
- 只測試順利路徑,跳過空值和邊界輸入。
- 錯誤訊息太模糊,沒有說明預期是什麼。
- 用 assert 驗證使用者輸入;-O 會把斷言從執行中的程式移除。
寫一個 square(n),斷言 square(4) == 16 和 square(0) == 0,然後列印 'ok'。
動手試試
改改變數、先預測輸出,再執行程式碼。第一次點擊「執行程式碼」時會下載 Python 執行時,可能需要幾秒鐘。
練習本課
12 道題,作答後立即看到解釋。