
t0mmy
2020年12月30日に参加
学習履歴詳細
単体テストの考え方/使い方 4章 読了
やったこと
- 単体テストの考え方/使い方 4章 読了
学んだこと
学び
- 退行保護に最大限備えるためには、テストの際にできるだけ多くのプロダクションコードを実行すること
- テストコードとプロダクションコードが密結合になっていると、false positive が発生しやすい
- false positiveの常態化は、テストが機能しなくなる原因となる、危険な状態
- 「退行保護」「リファクタリング耐性」「迅速なフィードバック」の三つは、トレードオフの関係
- 例) 「退行保護」「リファクタリング耐性」を最大限満たすと、速度が遅くなり、「迅速なフィードバック」は実現できない(E2Eテストなど)
- プロダクションコードの「what」ではなく「how」に目を向けているテストケースは、壊れやすい
- E2Eで検証するのは「アプリケーションにとって最も重要な機能、かつ、統合テストや単体テストで十分に検証できないテスト」のため
- 統合テストや単体テストで十分検証可能なテスト項目は、E2Eで検証する必要なし
- テストは、基本ブラックボックステストとして書く
- ブラックボックステストは、プロダクションコードに依存しないため、リファクタリングで壊れにくい(≒リファクタリングに耐性がある)ため
- ブラックボックステストで網羅出来ず、検証が必要な部分に限って、ホワイトボックステストを書く
気付き
- テストアラートの話は、運用やセキュリティに通ずるものがある
- 過剰なアラート(誤検知含む)は、オペレーターの注意を削ぐ
- 見逃しは、あってはならない
- プロダクションコードを呼び出す側の視点(つまりブラックボックステスト)でテストを書くと良い
- ホワイトボックス的なテストは、実装の詳細に強く依存するため、リファクタリングで破壊されやすい
- 「コンパイルエラーを伴わない false positiveは修正が困難」とは、言い換えると、コンパイルエラーや文法エラーを伴うテスト失敗は、修正しやすい
- => テストの失敗を、コンパイルエラーや文法エラーで検出できるようなテストは、壊れても修正しやすいテスト
- つまり、テストは大きく三種類に分かれる
- 壊れにくいテスト(≒リファクタリング程度では壊れないテスト)
- 壊れやすいけど、修正しやすいテスト(問題個所を、コンパイルエラーや文法エラーで検出できる)
- 壊れやすく、修正しにくいテスト(動きはするし、値も返すが、assert でコケるテスト。バグなのか、実装なのか区別が困難)
メモ
この章で扱う事
- 良い単体テストを構成する性質の大きな分類
- 理想的なテストについての定義
- テスト・ピラミッドについて
- ブラックボックステストとホワイトボックステストの使い方
単体テスト 4つの柱
柱1 たくさんバグを検出できること(退行保護)
- 特に、ドメインロジックは、たくさんバグを見つけたい
- 反対に、UIやgetter/setter部分は、動くことの確認程度に抑える
- 必要なら、外部依存部分も含めて、想定通りに動くことをテストする
- 退行保護に最大限備えるためには、テストの際にできるだけ多くのプロダクションコードを実行すること
柱2 プロダクションコードのリファクタリングによって、テストが簡単には壊れないこと
- テストコードとプロダクションコードが密結合だと、リファクタリングによってテストコードが壊れやすい
- テストコードが実装に追いついていない(言い換えると、テストコードに問題がある)この状態を、書籍では false positive と呼んでいる
- false positive は、以下に示す単体テストの利点を潰してしまう
- テストを実行することで、プロダクションコードに埋め込まれた問題に気付くことが出来る
- false positive によるテスト失敗が常態化してしまい、プロダクションコードのミスに気付けなくなる
- テストを実行することで、「プロダクションコードが退行していないこと」を確認できる
- false positive によるテスト失敗が常態化してしまい、誰もテストを信用しなくなる
- 最悪、退行を防ぐ手段として「可能な限りコードを変更しないこと」という戦略が採択される
- 特に、コンパイルエラーを伴わない false positive は、バグとの区別が困難であり、調査に多くの労力が必要
柱3 迅速なフィードバック
- テストが短時間で完了できると、開発者は頻繁にテストを実施し、結果としてプロダクションコードのバグを早期に発見できる
柱4 保守しやすさ
- テストにて、何を検証しているのか把握しやすいこと
- テストの実施(実装できるまで準備する)容易さ
テストピラミッドとは
- テストピラミッドにて E2E が最上位に位置する(≒最もテストケースが少ない)とされる理由
- E2Eで検証するのは「アプリケーションにとって最も重要な機能、かつ、統合テストや単体テストで十分に検証できないテスト」のため
- E2Eにこそ、不要なテストケースを持ち込まないようにしたい
ブラックボックステストとホワイトボックステスト
- ブラックボックステストはinとout を、ホワイトボックステストは、プロダクションコードの詳細を検証する
- ホワイトボックステストは、プロダクションコードに強く依存するため、リファクタリングによって壊れやすい
- 基本的に、テストはブラックボックステストとして書くことになる
- ブラックボックステストで網羅できない部分を、例外的にホワイトボックステストとして書く ... という運用になる
まとめ
良い単体テストを構成する柱は、以下の4つ。
- 退行(regression、つまりバグ)に対する保護: たくさんバグを検出できるか
- テストにより、どれだけ多くのバグを検出できるか
- 「退行に対して保護されている」状態とは、テストによってより多くのバグを検出できる状態を示す
- リファクタリングへの耐性: リファクタリングした時に、テストが壊れにくいか
- false positive を押さえつつ、プロダクションコードをリファクタリングできるかを示す性質
- false positive : プロダクションコードは正しいのに、失敗してしまうテスト - テスト失敗に慣れてしまい、テストの失敗に注意を払わなくなる - テストへの信頼が失われる
- 「リファクタリングへの耐性が高い」状態とは、バグのみを、バグとして警告するような状態を示す
- 迅速なフィードバック
- テストが完了する速度
- 保守容易性
- テストにて、何を検証しているのかの把握しやすさ
- テストの実施(実装)容易さ
- 「退行保護」「リファクタリングへの耐性」「迅速なフィードバック」は、トレードオフの関係
- 最大限に備えることが出来るのは、二つまで
- テストが増えるほど、遅くなるよね?
- テストケースの作成にはブラックボックステストを、分析にはホワイトボックステストを用いる
- ブラックボックステストにより、実装の詳細に依存しなくなる
テスト
2023年03月20日(月)
2.0時間