前回までのコード
def enumerate_prime_number_under(n):
prime_numbers = []
for m in range(2, n):
if is_prime_number(m) == True:
prime_numbers.append(m)
return prime_numbers
def is_prime_number(n):
for m in range(2, n):
if n % m == 0:
return False
return True
from tdd_prime.prime_enumerator import enumerate_prime_number_under, is_prime_number
def test_prime_enumeration():
assert enumerate_prime_number_under(10) == [2, 3, 5, 7]
def test_prime_judge_true():
assert is_prime_number(7) == True
def test_prime_judge_false():
assert is_prime_number(14) == False
リファクタリング
前回までで、機能の実装を完了することができました。次にすべきことは、コードの設計や関数名の変更等を行うなどのリファクタリングとなります。これまでに用意したテストがあるため、変更によりコードが破壊されていないか確認しつつリファクタリングを行うことができます。enumerate_prime_number_under
という名前は、長く、意味が掴みづらいため名前を変更して次のようなクラスにまとめます:
class PrimeEnumerator:
def enumerate(self, upper_bound: int):
prime_numbers = []
for m in range(2, upper_bound):
if is_prime_number(m) == True:
prime_numbers.append(m)
return prime_numbers
def _is_prime_number(self, n):
for m in range(2, n):
if n % m == 0:
return False
return True
テストを実行すると、失敗します。関数のインターフェイスを変えたため、テストも変更する必要があります:
from tdd_prime.prime_enumerator import PrimeEnumerator
def test_prime_enumeration():
assert PrimeEnumerator().enumerate(10) == [2, 3, 5, 7]
def test_prime_judge_true():
assert PrimeEnumerator()._is_prime_number(7) == True
def test_prime_judge_false():
assert PrimeEnumerator()._is_prime_number(14) == False
この変更で、テストが成功することが確認できます。このように、TDDを用いた開発では、まずは動くコードを書き、その後、動く状態を保ったままリファクタリングを行い、綺麗なコードに修正するといったステップで進みます。
まとめ
TDDには以下の利点があるとよく言われています:
- テストから考えることで、実装したい機能の仕様を明確にした上で実装に着手できる
- 細かいステップを確実に踏むことで、動くことが保証されたままでコードに変更を加えられる
- テストしやすい作りにできる
一方で、各ステップをどのくらいの大きさにすべきかなど、考えるべきことは多いため、ほどほどにTDDを活用するのがちょうど良いと感じました。