Python unittest 單元測試
當程式碼規模變大後,手動測試每個功能會變得極其低效。Python 內建的 unittest 模組借鑒了 Java 的 JUnit,提供了一套完整的框架來撰寫、組織與執行自動化測試。
基礎架構
要撰寫一個測試,你需要建立一個繼承自 unittest.TestCase 的類別,並定義以 test_ 開頭的方法。
# calculator.py (被測試的目標程式)
def add(a, b):
return a + b
def divide(a, b):
if b == 0:
raise ValueError("除數不能為零")
return a / b
# test_calculator.py
import unittest
from calculator import add, divide
class TestCalculator(unittest.TestCase):
# 測試加法
def test_add(self):
self.assertEqual(add(1, 2), 3)
self.assertEqual(add(-1, 1), 0)
# 測試異常處理
def test_divide_error(self):
with self.assertRaises(ValueError):
divide(10, 0)
# 直接執行這個檔案
if __name__ == '__main__':
unittest.main()
常用的斷言 (Assertions)
斷言是用來判斷「實際結果」是否符合「預期結果」的方法:
| 方法 | 檢查內容 |
|---|---|
assertEqual(a, b) | a == b |
assertNotEqual(a, b) | a != b |
assertTrue(x) | bool(x) is True |
assertFalse(x) | bool(x) is False |
assertIsNone(x) | x is None |
assertIn(a, b) | a in b |
assertRaises(Error) | 應該拋出特定異常 |
設置與清理:setUp 與 tearDown
如果每個測試方法都需要準備相同的環境(例如建立資料庫連線或讀取設定檔),可以使用 setUp()。
class TestDatabase(unittest.TestCase):
def setUp(self):
# 每個測試方法執行「前」都會執行
print("準備環境...")
self.data = [1, 2, 3]
def tearDown(self):
# 每個測試方法執行「後」都會執行
print("清理環境...")
def test_sample(self):
self.assertIn(1, self.data)
如何執行測試?
- 直接執行腳本:
python test_calculator.py - 使用模組自動發現(最常用):
在專案根目錄執行以下指令,它會自動搜尋所有檔名為
test_*.py的檔案並執行。python -m unittest discover
總結
撰寫單元測試雖然在初期會增加開發時間,但它帶來的好處是巨大的:
- 防止回歸 (Regression):修改舊程式碼後,能快速確認是否破壞了現有功能。
- 敢於重構:有測試保護,你才能大膽地改進代碼結構。
- 作文件使用:測試案例本身就是最棒的程式碼範例。
如果你的專案很大,業界也常用第三方套件 pytest,它的語法更簡約且功能更強大,但底層仍然可以運行
unittest 寫的測試案例。