テスト駆動開発について

テスト駆動開発の基礎知識。

TDDとは

汚いコードとは

以下が含まれていると「汚いコード」になる。

  • 密結合
  • 多重ネスト
  • 巨大なクラス
  • 多すぎる引数
  • 多すぎる責務

TDDは分割統治

「動作するきれなコード」を目指して次の2つに分けて近づけていく。

  • きれいなコード
  • 動作するコード

TDDの目的

TDDに必要なこと

  • 問題を小さく分割する
  • 開発の歩幅を調整する
    1. テスト → 仮実装 -> 三角測量 -> 実装
    2. テスト → 仮実装 -> 実装
    3. テスト → 明白な実装
  • テストの構造化
  • リファクタリング
  • テスト作成、テスト実行、実装を素早くテンポよく繰り返す

TDD三大原則

  • 失敗するてユニットテストより先にプロダクションコードを書かない
  • テストケースが適切に失敗するまで次のテストケースを書かない
  • 全てのテストケースが成功するまで次のプロダクションコードを書かない

TDDのサイクル

  1. 目標を考える
    • テキストで目標を書き出す
    • テスト容易性の高いもの、低いもので目標を分ける
    • 目標の中から書くテストをを決める(テスト容易性が低いものを基準に選択)
  2. 目標を示すテストを書く
  3. テストを実行して失敗させる(Red)
    • テスティングフレームワークが正しく動作していることを最初に確認する
    • 最初のテストは設計要素が多いので作業が重い
  4. 目的を達成する最低限のコードを書く
    • コピペでも良いのでとにかく動作させる
  5. テストを成功させる(Green)
    • テストコードのテストは最初に行う(仮実装)
  6. テストが通るまでリファクタリングを行う(Refactor)
    • テストが成功したままで中身を改善する
    • プロダクション、テストどちらのコードも行う
  7. 1-6を繰り返す
    • 繰り返す回数は事前に決める

TDDが苦手なところ

  • DBやUIがテスト実行に制約があるコンポーネントのテスト
  • プロトタイピング等で抜本的な変更が頻繁に行われるコード
  • 処理に時間がかかるコードのテスト

テストのアンチパターン

  • assertは縦に並べない
    • どのテストが失敗しているか分かりにくい
    • テストが失敗すると実行されないテストが発生する
    • アサーションルーレット」と呼ばれる
  • テスト同士に依存性を持たせない
    • 並列分散実行できなくなる

ドキュメントとしてテストを機能させるには

  • テスト名を抽象化しない
    • テスト名を具体性の高いものにする
    • テスト項目をTodoリストと同じような階層構造にする
  • 無意味な重複したテストは削除する
    • 三角測量用のテスト
    • テストの不安を解消するためのテスト