昨天成功處理了 1、2、3,但 4 輸出 "IIII" 而非 "IV"。今天用 TDD 處理羅馬數字的減法規則。
核心規則:
建立 tests/day12/test_roman_converter_4.py
from src.roman.converter import to_roman
def test_convert_4():
assert to_roman(4) == "IV"
測試失敗 🔴:Expected: "IV", Received: "IIII"
更新 src/roman/converter.py
def to_roman(number: int) -> str:
if number <= 0:
raise ValueError("Number must be positive")
if number == 4:
return "IV"
result = ""
for _ in range(number):
result += "I"
return result
測試通過 🟢
建立 tests/day12/test_roman_converter_5.py
from src.roman.converter import to_roman
def test_convert_5():
assert to_roman(5) == "V"
測試失敗 🔴
更新 src/roman/converter.py
def to_roman(number: int) -> str:
if number <= 0:
raise ValueError("Number must be positive")
result = ""
if number >= 5:
result += "V"
number -= 5
if number >= 4:
result += "IV"
number -= 4
for _ in range(number):
result += "I"
return result
建立 tests/day12/test_roman_converter_6_7_8.py
:
from src.roman.converter import to_roman
def test_convert_6():
assert to_roman(6) == "VI"
def test_convert_7():
assert to_roman(7) == "VII"
def test_convert_8():
assert to_roman(8) == "VIII"
測試通過 ✅
建立 tests/day12/test_roman_converter_9.py
from src.roman.converter import to_roman
def test_convert_9():
assert to_roman(9) == "IX"
測試失敗 🔴:輸出 "VIIII" 而非 "IX"
更新 src/roman/converter.py
def to_roman(number: int) -> str:
if number <= 0:
raise ValueError("Number must be positive")
result = ""
if number >= 9:
result += "IX"
number -= 9
if number >= 5:
result += "V"
number -= 5
if number >= 4:
result += "IV"
number -= 4
for _ in range(number):
result += "I"
return result
建立 tests/day12/test_roman_converter_10.py
from src.roman.converter import to_roman
def test_convert_10():
assert to_roman(10) == "X"
更新 src/roman/converter.py
def to_roman(number: int) -> str:
if number <= 0:
raise ValueError("Number must be positive")
mappings = [
(10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I")
]
result = ""
for value, symbol in mappings:
while number >= value:
result += symbol
number -= value
return result
測試通過! 🟢
重構 成映射表形式(同上)。
測試通過! ✅
透過 TDD,我們發現羅馬數字的重要模式:
建立 tests/day12/test_roman_converter_complete.py
import pytest
from src.roman.converter import to_roman
def test_convert_1_to_10():
expected = [
(1, "I"), (2, "II"), (3, "III"), (4, "IV"), (5, "V"),
(6, "VI"), (7, "VII"), (8, "VIII"), (9, "IX"), (10, "X")
]
for number, roman in expected:
assert to_roman(number) == roman
def test_invalid_numbers():
with pytest.raises(ValueError):
to_roman(0)
with pytest.raises(ValueError):
to_roman(-1)
完整實作 src/roman/converter.py
def to_roman(number: int) -> str:
"""
將阿拉伯數字轉換為羅馬數字
Args:
number: 要轉換的正整數
Returns:
對應的羅馬數字字串
Raises:
ValueError: 當輸入非正整數時
"""
if number <= 0:
raise ValueError("Number must be positive")
mappings = [
(10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I")
]
result = ""
for value, symbol in mappings:
while number >= value:
result += symbol
number -= value
return result
執行測試:
pytest tests/day12/ -v
所有測試通過!我們有了處理 1-10 的羅馬數字轉換器。
試著思考以下問題:
今天我們成功實作了 1-10 的羅馬數字轉換,從最簡單的 if-else 開始,逐步演進到優雅的映射表模式。這就是 TDD 的魅力 - 讓我們的程式碼隨著測試逐步進化。
每個測試都像是一個小小的里程碑,紅燈告訴我們方向,綠燈確認我們走對了路,重構讓我們的程式碼更加優雅。這就是 TDD 的節奏感!
今天的 TDD 之旅就到這裡,明天我們繼續深入探索! 🚀