🌊

『単体テストの考え方/使い方』読書メモ

2023/07/17に公開

メタ

  • kindle版は固定レイアウトなのでスマホだと読みにくい
    • 図表もそこそこある
    • タブレット端末やPCなどでかい画面で読むと良い
  • 400ページあるので、少なくはない分量
    • どちらかというと前半を読むのに時間を使った
    • 後半は前半の内容を踏まえると、そこそこスラスラ理解できる
  • (おそらく分かりやすさのために)主張が厳密に一貫していないように感じることがあったので、一部分だけ読むより、はじめから通して読んだほうが理解がはかどると思われる
    • 考え方の初出時は緩めの紹介にとどまっていて、後から詳細な説明になるイメージ
  • オブジェクト指向プログラミング色の強いプログラミング言語を利用しているため、そうではないプログラミング言語への適用はベストマッチという感じではないように思った

読書メモ

  • プロダクションコードもテストコードも無いに越したことはない
    • 必要なテストだけを書くことが、ソフトウェアの発展に寄与する
    • 必要なテストが無いと、ソフトウェアの発展が妨げられる

  • タイトルから単体テストにフォーカスした内容を想像するが、単体テストが分かると単体じゃないテストも分かるようになるという考えから、統合テストなどにも章を割いて踏み込んでいる
    • ソフトウェアのテストコードは、単体テストと統合テストのふたつに分類できる
  • 単体テストの解釈は別れており、代表的なものが「古典学派」と「ロンドン学派」である
    • 古典学派はテストケースが他のテストケースから独立していることを単体と解釈している
    • ロンドン学派はテスト対象が依存から独立していることを単体と解釈している

  • 良い単体テストは、以下の要素を備えている
    • 退行に対する保護
      • false negativeが少ないこと
    • リファクタリングへの耐性
      • false positiveが少ないこと
    • 迅速なフィードバック
      • 実行時間が短いこと
    • 保守のしやすさ
  • 保守のしやすさは常に最大限に備えるべき
    • 他の要素とのトレードオフが無いため
  • 退行に対する保護、リファクタリングへの耐性、迅速なフィードバックは、このうち最大で2つしか最大限に備えることはできない
    • 最善なのは、リファクタリングへの耐性を最大限に備え、退行に対する保護と迅速なフィードバックのトレードオフの中でバランスを取ること
      • ソフトウェアの発展においてリファクタリングができることが重要だから
      • 退行に対する保護に寄ったテストがE2Eテスト、迅速なフィードバックに寄ったテストが単体テスト、その中間が統合テスト

  • テストダブルは、モックとスタブに分類される
    • モックはテスト対象から依存先へのコミュニケーションを模倣・検証する
    • スタブは依存先からテスト対象へのコミュニケーションを模倣する
  • 観察可能な振る舞いをするシステム間コミュニケーションにモックを使う
    • それ以外は実装の詳細でありモックを使うと、テストコードが増えるしテストの効果が減るため

  • 単体テストの手法として、出力値ベーステスト、状態ベーステスト、コミュニケーションベーステストがある
    • 出力値ベーステストが最も費用対効果が高い
    • 出力値ベーステストへのリファクタリングには、ヘキサゴナルアーキテクチャや関数型アーキテクチャの考え方が利用できる

  • テストすべきコードは、「コードの複雑さ・重要性」と「協力者オブジェクトの数」の2軸から分かる
    • ドメインモデル/アルゴリズムは単体テストが最適
      • プロセス外依存が無いため出力値ベーステストが使いやすいため
    • コントローラは統合テストが最適
      • プロセス外依存との統合を検証できるため
    • 過度に複雑なコードはテストのコストが高いため、ドメインモデル/アルゴリズムとコントローラに分離するリファクタリングをすべき
    • 取るに足らないコードはテストすべきでない

  • 統合テストでは、管理下にない依存のみをモックに置き換える
    • このときできるだけ外部に近い部分をモック対象にする

  • データベースへの書き込みは読み込みよりもテストする価値が高い
  • データの変更を行う場合に、ドメインモデルが役に立つ
    • データを変更しない場合は、ドメインモデルを経由しなくてもよい

Discussion