なぜユニットテストをつかうの?といわれた時に答える

2019年10月28日 00時10分

使わない時の生産性<使った時の生産性(学習コスト含)なる。私たちは仕様書やユーザーの求める機能を実装する仕事をしている。できた成果物はテストを通ってユーザーに届けられる。ここまでは恐らく共通だろう。

納品以降の瑕疵を考えなければ(倫理的にどうかという議論は置いておいて)、動くものを最短で納品することが営利企業として正しい選択である。

ただ、納品後も関係が続くのであればホワイトボックスで動作検証はしていった方が、保守・管理まで見据えた際には結果的にコストが小さくなる。

手戻りのコストが後工程になるにつれて指数関数的に大きくなる以上、要件の時点で動作を規定できるユニットテストを先に実装しておくスタイルーいわゆるテスト駆動開発で実装していきたい。

関数の機能を確認するユニットテストは開発者目線では有用だし、バックエンド側の動作確認だけなら導入コストは低い。ビジネスロジックを全ての工程が完了した後に検討するスタイルより、各関数で検証可能な状態の方が原因の切り分けや動作検証が容易であることから導入前後で生産性は上がる。

ユニットテストはコンポーネントや関数に対して行うテストなので、ある程度のシナリオを含んだテスト、いわるゆ画面単位での単体テストにおいて、互換性がある訳ではない。

ただ、ユニットテストを組み合わせていきながら、抽象度を高くしていくのであれば xUnit 系列のツールで検証はできるけれど、それは結合テストであって、ユニットテストではないのではない何か。結合テストを想定するなら、今っぽく selenium 等のスクリプトを書いて、極力ヒューマンエラーが起こりにくい仕組み作りを。

テストケースは、分析をして重要ケースを抑えたのちに、直交表を利用して網羅率を上げて効率よく実装する。

なぜ xUnit 系列を使用するのか

バックエンド側の挙動はブラウザで動作させる場合、すべての処理を行った後ブラウザに表示される結果を見て判断するしかない。入力と出力の比較しかできない、つまりバックエンド側はブラックボックスになっている。

xUnit 系は関数やシナリオ事に返り値と比較を行うことのできる assert 関数がある。これによりブレークポインやコンソールで処理を確認して数値を確かめるしかなかった関数ごとの処理を、目視で繰り返し明示することができる。

ヒューマンエラーが非常に怖いので、できる限りコードで記述できるテストルールを推したい。

モックツールと併せることで関数間の依存度をコントロールできる記述もできる。返り値を明示する、副作用の少ない実装(インプットのみから関数の結果が導出される)といったおまけもある。

デメリット

工数、教育コスト、技量の差でカバレッジが変わる。

新規の技術を入れるのであれば乗り越えないといけない壁ではあるけれど、モブプロ、ペアプロの仕組み作りやっていきたい。

ユニットテストをカバレッジで判断するのではなく、複雑な関数に絡み合ったモジュール内での動作を担保するように実装していくのが良いとは思った。後押ししている記事もあった。

TDD のテストは使い捨てでいい

TDD のテストはプログラマのこまごまな課題に応じて累積的に作られるため、保守コストがかかるテスト・保守する価値の低いテストが生まれがちです。そのためテストの使い捨ての発生はむしろ自然な流れです。
また TDD のテストはプログラマの不安を解消するといった軽い動機付けで作ってよいので、ゆるい動機でテストを書いて、ゆるい判断でテストを捨てていくスタイルでも、TDD は効果を出せます。

千里霧中 -TDD はゆるく実践しても大丈夫

xUnit 系のテストモジュールはあると便利だと思うし、今までの開発でそういったブレークポイントでやりくりしていた時期もあったので、処理を止めて追うのも大切だけど、テストを書く方が振る舞いを定義しやすくなる。

TDD について

いきなり処理を一気に書いて詰まる場合は結構ある。そういった時にテスト駆動開発は大きな力になる。いきなり全ての処理ぞ実装するのではなく、理想てきな振る舞いについてテストで定義を行い、そのテストに通るように実装を進めていく。

決まった開発手法で行った方が開発効率も高まるというデータが CodeComplete には記載がある。何らかの指標がないまま実装を行うのではなく、チーム全体で決めた指針に則って実装を行なっていきたい。