Clean Code ch9 Unit Tests

Clean Code勉強メモ

出典: 

Unit Tests

  • 昔は「単体テストコード」は書き捨てのものだった
  • 今では、テストコードは実装と同じバージョン管理下におかれ、他の人も実行できるように
  • 多くのプログラマが自動化単体テストを取り入れるようになった
  • が、「良いテストを書く」という観点を見逃しがち

The Three Laws of TDD

  • 「テストを最初に書く」というのは氷山の一角
  • 三原則

    • 落ちる単体テストを書く前にプロダクションコードを書かない
    • 落ちるのに十分なぶん以上のテストを書かない

      • コンパイルは通す

        • さもないとテスト自体を実行できないから
    • 現在落ちているテストを通すのに十分なぶん以上のプロダクションコードを書かない
  • これらを守ると、30秒そこらのサイクルを回すことになる
  • テストとプロダクションコードは一緒に書かれる

    • テストが数秒先行するけど
  • 日に数十、月に数百、年に数千ものテストを書くことになる

    • プロダクションコードに匹敵する物量になる
    • ここにおいて、テストコードの管理の問題が生じてくる

Keeping Tests Clean

  • プロダクションコードと同様に重要

    • 二級市民ではない
    • ちゃんと考え、設計し、大事に扱うべきもの
  • 汚いテストコードは、テストコードが無いよりも悪いまである

    • 新しいテストを追加するのが困難
    • プロダクションコードに変更を加えて、既存のテストが落ちたとき、再び通すのが困難
    • 結局捨てられたりする

Tests Enable the -ilities

  • テストはプロダクションコードに柔軟性・保守性・再利用性をもたらす
  • テストが無いと変更には恐怖がつきまとう

    • どんなにアーキテクチャが優れていようが、どんなに良く設計してモジュールを分割していようが、変更がバグを埋め込んでいない保証がない
  • テストがあると、この恐怖はほとんど無くなる

    • カバレッジが高いほど恐怖は少なくなる
    • 設計の改善などを恐れることなく行える
  • テストが汚いと、この柔軟性等が失われる

    • 【補】気軽にテストを追加できない・落ちたテストを再度通せないから
  • テストが汚いとプロダクションコードも汚くなる
  • しまいにはテストを失い、プロダクションコードは腐っていくことになる

Clean Tests

  • 1に可読性、2に可読性、3に可読性

    • プロダクションコードにおけるそれよりも重要
  • 可読性を高めるには

    • 明確さ
    • 単純さ
    • 表現の密度

      • 少ない表現で多くを言いたい
  • build-operate-check パターンでテストの構造を明瞭にする

    • build

      • テストデータの構築

        • 【補】モックの準備とかもここ
    • operate

      • テストデータに対して操作を行う
    • check

      • 操作により期待通りの結果が得られていることをチェック
  • テストの意図をぼかしてしまうような瑣末な詳細は別の関数に押し込める

Domain-Specific Testing Language

  • build-operate-checkパターンを適用し、詳細を押し込めた関数は、テスト用のDSLになる
  • 前もって用意するというよりは、テストコードをリファクタリングしていく中で育つもの

A Dual Standard

  • テストはプロダクションコードと同様に大事に扱うべきだが、異なる部分も存在する
  • 「きれいに保つべき」という点は共通
  • 効率面の要求は異なる

    • テストコードはプロダクションコードほど高効率である必要はない
    • 効率と引き換えに可読性の高いDSLをつくるという選択

One Assert per Test

  • 厳守となると辛い

    • テストコードが重複してしまう
    • まとめるには?

      • Template Method Pattern?
      • @beforeとか使う?
    • やりすぎでは
  • ボブおじ見解: 1つのテスト中のアサートの数は最小限にとどめるべきだが、1つにこだわる必要もない

Single Concept per Test

  • 1つのコンセプトあたりのアサート数は最小限に
  • 1つのテスト関数あたり1つのコンセプト
  • 【所感】dockerコンテナのベストプラクティス「1コンテナ=1関心事」に似てますね

    • 1関心事は1プロセスとは限らない

F.I.R.S.T.

  • F: Fast

    • テストは高速であるべき
    • テストが遅いと、こまめに実行しなくなる
    • こまめに実行しないと、問題の発見が遅れて、簡単に修正できなくなる
  • I: Independent

    • テストケース間に依存関係があるべきではない
    • 依存関係があると、1つコケると後続もコケて、診断が難しくなる
  • R: Repeatable

    • 任意の環境で反復可能であること

      • 商用環境
      • QA環境
      • 手元のラップトップ(オフライン)
    • さもないと

      • テストが落ちたとき言い訳するようになる
      • 「テスト用特定の環境」が利用不可能になるとテストを実行できない
  • S: Self-Validating

    • 結果は2値であること

      • 通ったか、落ちたか
    • 通ったかどうかの判定を人間が行うべきではない

      • 主観に影響されてしまう
      • 長時間の手作業を要する
  • T: Timely

    • プロダクションコードを実装する直前に書く
    • 後から書こうとすると、コードがテスト困難なつくりだったりする

英語

  • concoct

    • 混ぜて作る
    • でっち上げる
  • cobble

    • つぎはぎして雑に作り上げる
  • come a long way

    • ずっと進歩する
  • nook

  • cranny -隙間
  • join the ranks of

    • 仲間入りする
  • watchword

    • 合言葉
  • impunity

    • とがめなく、無事に
  • hamper

    • 妨げる
  • inundate

    • 押し寄せる
    • 氾濫する
  • draconian

    • 極めて厳しい in a timely fashion
    • タイミングよく