Robert C. Martin先生のCleanCode第9章を読んだメモ。

テスト(第9章)の概要

  • TDD三原則
    1. 失敗する単体テストコードを書く前に、製品のコードを書いてはいけない。
    2. コンパイルが通り、適切に失敗する単体テストができるまでは、次のテストを書いてはいけない
    3. 現在失敗している単体テストが通るまで、次の製品コードを書いてはいけない。
  • テストを綺麗に保つ
    • 汚いテストはテストを持たないのと同値
      • 未満ではない。
      • 変更が難しくなる。
    • テストも製品コードと同様に重要
    • 汚いテストはメンテナンスコストが高い
  • テストをXXX性を可能とする。
    • コードの柔軟性、保守容易性、再利用性を維持、提供しているのは単体テスト。
      • テストがあれば変更が怖くないから。
      • アークテク茶と設計を綺麗にするためのキー
    • テストコードが汚いと最終的にすべて失い、コードが腐る。
  • クリーンテスト
    • 読みやすくしろ。
  • ドメイン特化テスト言語
    • fixtureやassertをメソッドとしてまとめて、詳細な処理を隠す?
  • 二重規範
    • テストは本番環境では実行されない。
    • 処理のassertなどもまとめて検証できるように複数の確認項目を1度に返すシンタックスシュガーのようなメソッドを定義するのもアリ
    • メモリやCPU使用率などの効率は無視して良い。
  • 1つのテストに1つのアサート
    • デイブ・アテルの見解の道場的には、1つのテストには1つのアサート文までとするべき
    • 全く同じ実行でもテストメソッドを分けて検証することも検討する。
    • 実行が同じならテンプレートメソッドパターンなどで重複を防げるはず。
    • しかし、2つ以上のassertを実装してもRobert C. Martin的には良いと思っている。
      • 可能な限りassertを減らす努力はしましょう。
  • 1つのテストでは1つの概念を扱う
    • ごちゃ混ぜ(関数Xを引数を変えて何度も実行して都度、結果をassertする)にテストを実行してはいけない
    • テストは短くしなさい。
    • テストに抜けがあった場合など、どこに追加すればよいか、どこまで書かれているのか把握しにくくなる?
  • F.I.R.S.T
    • First…高速に書く
      • 時間がかかると頻繁に実行する気が削がれる。
      • 修正が容易な時期に問題に気づくことができなくなる。
      • コードを綺麗にするのが億劫になる。
    • Independent…独立している
      • 好きな順序でテストができるようにしておく
      • 後続テストの失敗につながる。
      • テストの後半部の問題を隠すことになる。
    • Repeatable…再現性がある
      • どんな環境でも再現可能にする。
        • 帰宅途中のネットワークに繋がっていないノートPCでも
      • テストを失敗する言い訳を抱えることになる。
      • 特定のテスト環境がなければテストできないという事実に気づかされることになる。
    • Self-Validating…自己検証可能
      • 成功か失敗かのどちらかを出力する。
      • 2つのテキストファイルを見比べてテストが成功したのかどうかを確認するのは避ける。
      • 失敗の判定が属人的になってしまう。
      • 長時間を要する手作業の検証が必要になってしまう。
    • Timely…適時性がある
      • 必要な時にすぐ書けるようにする必要がある。
      • 製品コードの前に書くこと。
      • 製品コードがテストしづらいものになっていることに気づくことができなくなる。
      • テストが困難なコードを設計してしまうことになる。

感じたこと

テストはないよりは、読みにくくてもあった方がマシだとは思っている派なので、テストを持たないのと同値は言い過ぎだと思った。
関数でassertや実行をまとめるのは、目から鱗ではあった。(いっぱいassert書いてた。。。)
本書には、TDD三原則
として 現在失敗している単体テストが通るまで、次の製品コードを書いてはいけない。 とあるが、誤訳ではないかと思う。

Robert C. Martinのブログ では以下のように書かれており、本書の言葉とは異なる。

  1. You are not allowed to write any production code unless it is to make a failing unit test pass.
  2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
  3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test.

厳密には、失敗するテストを通すためのプロダクトコード以外を書かない ではないかと。(Clean Codeの英文の書籍は持っていないから翻訳が間違っているのか、Bobおじさんの考え方が変わったかどうかはわからないけど。。。)