業務でもTDDをやるのは有用だと思ってる。
個人的には必須だと思ってる。
いままで数カ所の現場で働いてきたけど、なぜかTDDを導入しているところは無かった。
有用だと思う理由とか経験
実装完了し、コードレビューや開発内手動実行テストが通った後、最終結合テスト段階で「意図通りに動作していない」という問題が発覚する事がちょいちょいあった。
一例としては「viewに現れないような部分のデータの値がおかしくなっててその時は発見されず、別の処理で問題が露出する」など。
(たまに単なる見落としもあった。)
別に確認時に手を抜いたとかではなくて、こういう類のバグをコードレビューや手動テストで洗い出すのは現実的ではないのだと思っている。
コードレビューで「変数名がtypoしてて意図しないnull値が挿入されている」とか、見つけられる人は見つけられるのかもしれないけど僕は90%見逃してしまう。
コードレビューは「何も知らない人がコードだけ見て処理をどれくらい理解しやすいものになってるか?」とか「処理ロジックが間違ってないか?」「見落としているパターンが無いか?」あたりをチェックするくらいが効率が良さそう。
TDDしづらいパターン
新規ロジックを組む場合なら簡単にTDDを始められるが、既存ロジックに修正を入れる場合、まず既存ロジックにテストを追加しなければならない。 これが難しい場合が多い。
難しい理由は「処理が分割されていない」から。
たとえば、Aというメソッドは2パターンのテストで網羅できるとする。
同様にBメソッドは3パターン、Cメソッドは2パターンで網羅できるとする。
AとBとCメソッドを使ったDメソッドがある場合、これをテストするには2 * 3 * 2 = 12パターンのテストを書かねばならない。
ここでA,B,Cに既にパターンテストが書かれている場合、これらの動作は保証されているので、Dメソッドの事情だけに注目してテストを書けばいいのでそれほど大変ではない。
テストが書かれていないシステムは、上記のA,B,Cがメソッドに分割されておらず、1つのDメソッドとして大きく組まれている場合が多い。
だからDメソッドに12パターンのテストを書かなければならない状態になっている。
(実際には他にも機能を含んでいて12パターンでは利かない。)
逆に言うと、TDDで開発する場合テストを先に書くので処理が分割されやすい。
TDDがいいと思う理由の一つ。
それでも無理やりTDDをやってみた
今回、Dメソッドに当たるものがAPIのコントローラーだったので、api単位でパターンテストを書いてTDDで実装を行った。
パターン数が膨大な為、網羅はできないが、結合テストで行うであろうパターンを検討してそのパターンを書いた。
コントローラーなので入力値はpostやgetパラメータ。
検証対象はDBに対する変更内容となる。
やってみて良かった事を以下に記載する。
既存実装の理解が深まった
テストを書いている時、律儀にDBのカラムデータ一つ一つの値を記述するので、データ構造に対する理解が深まった。
テストを書いているので再実行が容易になり、 ちょっとコードを変えてみて再実行し、結果データがどうなるかの確認のサイクルを早く回せた為、理解が深まった。
検証しやすかった
実装後、正しく動作しているかどうかは数十カラムあるデータ内容をみて判断する必要があるが、一度記述しておけば何度でも一瞬で検証できる。
TDDでなければこれらを修正するたびに確認するのは大変な作業だと思う。
手作業確認の場合、実際は関連しそうな部分だけを確認することで時間を短縮しているが、これだと思わぬところに影響が出ていることに気がつけない。
実際に思わぬところのデータに影響が出てテストが落ちた事が何度もあった。
先にテストパターンを考えることで見落としていた仕様に早期に気がつけた
先にテストパターンを考えることで見落としていた仕様に早期に気がつけた。(そのまま)
TDDでは拾えなかったこと
それでも漏れた事は色々あった。
・そもそもAPIの使い方が間違っていた
・データ構造の組み方を勘違いしていた
そもそもの実装仕様を勘違いしていて、それに合わせて実装してたので結合テストでエラーが発覚した。
こういった類いのものはTDDでも拾えない。
・テストを書いていなかった部分で発生したエラー
全てのパターンを網羅することは出来なかった為起きたエラー。
手動テストで拾われた。
職人の技に感謝。