TL;DR
- 既存のテストとそれを通るきれいなコードがあれば、実装の正しさを頭で考えなくても、コードを変えてテストを実行すればテストが教えてくれる。
- テストが意図せず失敗したら、変更を巻き戻してテストが通る状態に戻してから、新しいテストを追加する。
内容
本章でやったこと
サブクラスの times メソッドの実装の違いをなくすために、メソッド呼び出しのインライン化と、マジックナンバーの変数化というリファクタリングを行った。また、デバッグのためだけに使う toString メソッドを、テストを書かずに追加した。
次に、Franc の代わりに Money を返すように変更し、テストが落ちるかを確かめた(テストに聞いた)。テストが落ちたので、変更をいったん元に戻してテストを追加し、そのテストが通るように改めて実装した。
テストに聞く
既存のテストと、それを通るきれいなコードがあれば、実装の正しさを頭で考える必要はない。コードを変更してテストを実行すれば、テストが教えてくれる。サンプルコードでは、Franc と Money を区別する必要があるかが問題になった。テストに聞いた結果、問題の原因は equals にあった。調べるべきなのは通貨が等しいかどうかであって、クラスが同じかどうかではない。したがって、この 2 つを区別する必要はない。
toString のテストを書かなかった理由
toString のテストを書かなかった理由は 3 つある。
- 画面への出力をすぐに見たかった
- デバッグ出力のためのものであり、バグが入っても問題にならない
- 既存のテストが失敗しているときに、テストを追加するのは避けたい
テストが意図せず失敗したとき
テストなしで本番コードを変更してはいけない。また、テストが失敗している状態で新しいテストを追加するのも避けたい。代わりに、次の流れで進めるとよい。
- テストが失敗している原因の箇所を確認する
- 1 の変更を巻き戻し、テストが通る(グリーンの)状態に戻す
- 新しいテストを追加する
- 3 のテストが通るように実装を進める
キーワード
自分の理解
実装に迷ったら、テストを書いて仕様を探れ、ということだと理解した。TDD がテスト「駆動」開発と呼ばれるのは、このためなのだろう。