テスト駆動開発
〜速い開発速度を保ち、着実に開発を進める〜
テスト駆動開発とは
テスト駆動開発(TDD:Test Driven Development)は、とても小さな開発プロセスを繰り返す、ソフトウェア開発手法の一つです。
その方法は、
- まず失敗するテストを書きます
- 次にそれが通るコードを書きます
- 読みやすく、綺麗になるように、リファクタリングします
- 上記を繰り返します。
といった、とてもシンプルなメソッドです。
なぜ使うか
なぜ、TDDを行うのでしょうか。
それは速い開発スピードを永久に継続したいからです。
なぜTDDだと速い開発スピードを維持できるのでしょうか。
それは、
- 速く開発したい
- 速く開発をするためには、綺麗なコードが必要
- 綺麗なコードを維持するためには、リファクタリングが必要
- リファクタリングを好きな時にするためには、コードに対する自信が必要
- コードに対する自信を持つためには、テストが必要
では、いつテストを書くべきでしょうか。
実装前に書きましょう。
どうやって行うのか
基本は最初に書いた通り、下記のサイクルを回すことです。
- まず失敗するテストを書きます (できれば、どう失敗するのかを推測しましょう)
- 次にそれが通るコードを書きます (綺麗じゃなくていいのでテストが通る実装をしましょう)
- 読みやすく、綺麗になるように、リファクタリングします
- 上記を繰り返します。
この手法におけるコードに対する自信の扱い方について、
もう少し詳しく説明をします。
慣れている開発であれば、問題ないと思いますが、
慣れていないアプリケーションや慣れていても行き詰まってしまうなど、
開発中に不安がある時も多々あると思います。
そういった場合には、
TDDのサイクルを小さく回す、つまり、
開発のステップを小さくしてみてください。
例えば、足し算の関数を作る場合を想像してみてください。
いきなり、足し算を作ってエラーになった時、
足し方が悪いのか、数字の出力の方法が悪いのかわかりません。
まず、自分が理解していて、自信を持っている実装を促すようにテストを書きます。
例えば、まずは数字を出力する実装をし、
その後、足し算を実装します。
このように、確かなことから着実に進めるように開発のステップを小さくすることで
自信を持てますし、考えるべき対象を絞ることが可能になります。
もし、開発のステップを大きくして、いきなり足し算関数を作って失敗した場合に
出力が悪いのか、足し算の書き方が悪いのかが切り分けるのが大変です。 (このくらい簡単な関数なら大丈夫かもですが)
より複雑な関数になった場合はより大変になります。
また、頭でデバッグするよりも、テストを実行してしまった方が
圧倒的に速く答えを得ることができます。
言葉で説明してみましたが、この「開発のステップを自由自在にする」ことの強力さは、
実際に体験してみないと理解しづらいと思いますので
テスト駆動開発 を写経することをおすすめします。
注意点
テストで大事なこと
テストはただ書けばいいというわけではありません。
テストを書いていく上で意識すべき大事なことをご紹介します。
- 実装に依存していない(Freedom)
- 自信が持てる(Confidence)
- 速くテスト結果が得られる(Fast Feedback)
- わかりやすく、読みやすい(Clean)
実装に依存していない(Freedom)
挙動が変わらないように実装を正しく変更した際にテストが壊れてしまうようでは
リファクタリングを自信を持って行うことができません。
実装を変更しても、要件通りに正しく動いていれば成功するテストが良いテストです。
自信が持てる(Confidence)
きちんと挙動をチェックできているか不安なテストだと自信が持てません。
自信が持てないとリファクタリングができません。
実装の挙動を網羅しているのが、良いテストです。
速くテスト結果が得られる(Fast Feedback)
テストの実行に30分とか1時間、かかっていては
テストを何度も実行することができません。
それでは、速い開発にもならずにTDDのメリットがなくなってしまいます。
過不足なくテストがあり、それぞれのテストが独立しているのが、良いテストです。
わかりやすく、読みやすい(Clean)
テストが書いてあっても、何をテストしているのかわからないテストだと
自信を持てませんし、修正がしづらくなります。
わかりやすく、読みやすいのが、良いテストです。
よくある質問
テストがあればいいなら、後からテスト書けばいいのではないですか?
個人的にはおすすめしません。
テスト駆動開発は、テスト駆動設計だとも考えられます。
最初に実装を書いてしまうとテストの書きづらいコードになってしまう場合が多いです。
テストがほとんどないシステムでテストを書きやすいように必要な挙動を維持したままリファクタリングや追加実装をした際に、
とても大変な思いをした経験があります。
QAチームがいるから、テストコードはいらないと思いますが、いかがですか?
テストの大事な要素に速いフィードバックがあります。
全ての実装を作り終えた後にQAに渡し、
根幹の部分を直さないといけないようなバグを見つかる可能性もゼロではありません。
それをQAのタイミングまで待たなくてはならないのは時間がもったいないです。
テストを書かずにQAにテストをお願いし、
直すと他にも影響が出てしまうようなバグでリリースが延期したことがあると聞いたことがあります。
テスト書く時間があるなら実装する時間に当てたいのですが、いかがですか?
それでもいいでしょう。緊急で開発しないといけない場合など、
その瞬間の速度が大事であれば、決定次第だと思います。
ただし、ずっとその状態を続けるということであれば、それはお勧めしません。
テストのないコードはほぼ間違いなく、
開発すればするほど、開発速度が落ちていきます。
また、関係のない(と思われる)ところでデグレが生じるなど、
品質も低下すると予想されます。
さらに、テストがないことで気づけず、QAも関係ないと思っていた箇所なので見逃してしまい、
本番環境に出てしまうといった最悪の事態を経験したことがあります。
一時的にテストを書かないのは、仕方がないかもしれませんが、
余裕ができた際にテストを追加していくことをお勧めします。
テストのないアプリケーションを担当することになりましたが、どうすればいいですか?
追加開発する必要があるのであれば、
その周辺のコードを優先的にテストを追加していきましょう。
ある程度、自信が持てたら、実際にTDDで実装していきましょう。
必要がない部分に関しては、テストを追加しなくてよいですが、
今後、開発する予定があるのであれば、テストを追加していくとよいでしょう。
参考資料
さいごに
文章の改善のため、フィードバックや質問などありましたら、こちらからお願いいたします。