Project Implementation & Unit Testing
my-project/
├── main.py # 程式進入點
├── requirements.txt # 套件依賴清單
├── .gitignore # Git 排除清單
├── README.md # 說明文件
├── src/ # 主要程式碼
│ ├── __init__.py
│ ├── calculator.py
│ └── utils.py
└── tests/ # 測試程式碼
├── __init__.py
└── test_calculator.py
程式碼與測試分開,讓專案更易維護;__init__.py 讓資料夾成為 Python 套件,可以 import。
def get_grade(score: float) -> str:
"""將分數轉換為等級"""
if score >= 90:
return "A"
elif score >= 80:
return "B"
elif score >= 70:
return "C"
else:
return "D"
def calculate_stats(scores: list[float]) -> dict:
"""計算成績統計"""
if not scores:
raise ValueError("成績清單不能為空")
return {
"count": len(scores),
"average": round(sum(scores) / len(scores), 2),
"highest": max(scores),
"lowest": min(scores),
"passing": sum(1 for s in scores if s >= 60)
}
import pandas as pd
from src.calculator import get_grade, calculate_stats
def main():
df = pd.read_csv("students.csv", encoding="utf-8")
# 加入等級欄位
df["grade"] = df["score"].apply(get_grade)
# 計算統計
stats = calculate_stats(df["score"].tolist())
print("=" * 30)
print(" 成績報告")
print("=" * 30)
print(f"人數:{stats['count']}")
print(f"平均:{stats['average']}")
print(f"最高:{stats['highest']}")
print(f"最低:{stats['lowest']}")
print(f"及格:{stats['passing']} 人")
print()
print(df[["name", "score", "grade"]].to_string(index=False))
df.to_csv("output.csv", index=False, encoding="utf-8")
if __name__ == "__main__":
main()
對程式中最小的邏輯單位(函式)進行自動化測試,確保每個功能都符合預期:
不需要安裝,直接 import unittest 即可使用。
import unittest
from src.calculator import get_grade, calculate_stats
class TestGetGrade(unittest.TestCase):
def test_grade_A(self):
self.assertEqual(get_grade(95), "A")
self.assertEqual(get_grade(90), "A") # 邊界值
def test_grade_B(self):
self.assertEqual(get_grade(85), "B")
def test_grade_D(self):
self.assertEqual(get_grade(59), "D")
class TestCalculateStats(unittest.TestCase):
def test_basic(self):
stats = calculate_stats([80, 90, 70])
self.assertEqual(stats["count"], 3)
self.assertEqual(stats["average"], 80.0)
self.assertEqual(stats["highest"], 90)
def test_empty_raises(self):
with self.assertRaises(ValueError):
calculate_stats([])
if __name__ == "__main__":
unittest.main()
# 執行全部測試
python -m unittest discover tests
# 或執行單一測試檔案
python -m unittest tests.test_calculator
失敗時會告訴你哪個測試失敗、期望值是什麼、實際得到什麼。
import unittest
# 要被測試的函式
def fizzbuzz(n: int) -> str:
"""
n 能被 15 整除 → "FizzBuzz"
n 能被 3 整除 → "Fizz"
n 能被 5 整除 → "Buzz"
其他 → str(n)
"""
if n % 15 == 0:
return "FizzBuzz"
elif n % 3 == 0:
return "Fizz"
elif n % 5 == 0:
return "Buzz"
return str(n)
class TestFizzBuzz(unittest.TestCase):
def test_fizz(self): self.assertEqual(fizzbuzz(3), "Fizz")
def test_buzz(self): self.assertEqual(fizzbuzz(5), "Buzz")
def test_fizzbuzz(self): self.assertEqual(fizzbuzz(15), "FizzBuzz")
def test_number(self): self.assertEqual(fizzbuzz(7), "7")
unittest.main(argv=[""], exit=False, verbosity=2)
學會了專案結構規劃、模組拆分與 unittest 單元測試。