ブログ記事
リファクタリングでテストが壊れる理由:良いテストを作る4本の柱
コードを改善するたびにテストが壊れる——そんな状況に陥っていませんか? テストを増やしているのに開発スピードが落ちているなら、テストの「量」ではなく「質」に問題があるかもしれません。
Vladimir Khorikov の『単体テストの考え方/使い方』は、テストを「バグ発見ツール」として機能させるだけでなく、「プロジェクトが長期間成長し続けるための投資」と定義し直す観点から書かれた一冊だ。テストコードもメンテナンスが必要なコストである——この前提に立つことで、テストに投資する価値の判断軸が根本的に変わる。
1. 良いテストを評価する4本の柱
Khorikov は、テストの質を「感覚」で評価するのではなく、次の4軸で客観的に測ることを提唱している。
- 退行に対する保護: バグを検出できるか。コード量や処理の複雑さに比例して価値が高まる。
- リファクタリング耐性: 内部の実装を変えてもテストが誤って失敗しないか(偽陽性を出さないか)。
- 迅速なフィードバック: テストの実行速度が開発のリズムを壊さないか。
- 保守のしやすさ: テストコード自体が読みやすく、セットアップが簡単か。
4つすべてを同時に最大化することはできないが、「リファクタリング耐性」だけはバイナリ(あるかないか)の問題だと著者は言う。これが欠けているテストは、リファクタリングのたびに失敗して開発者を誤誘導する。本物のバグを見逃す温床になるため、値が「ゼロ」になった時点でそのテストは純粋なコストになる。
2. 「振る舞い」を検証することがリファクタリング耐性を生む
テストが壊れやすい根本原因の多くは、「中身の仕組み(実装の詳細)」をテストが知りすぎていることにある。
例えば「この関数の内部で、クラス A のメソッドが呼ばれたか」を検証するテストは、クラス A を別の実装に置き換えた瞬間、機能が正しく動作していても失敗する。これが偽陽性だ。
対照的に「最終的に何が出力されたか」「システムとして何が達成されたか」という「観測可能な振る舞い」だけを検証するテストは、内部の改善に影響されない。Khorikov が「古典学派(デトロイト学派)」のアプローチとして支持するのはこの考え方で、テストはエンドユーザーの視点から見える結果に絞るべきだという立場だ。
3. モックの使用を「管理外の依存」に限定する
一部の流派では、テスト対象クラスが使う協力オブジェクトをすべてモックに置き換えるアプローチをとる。テストが書きやすくなる反面、クラス間の呼び出しパターンという実装の詳細にテストが密結合してしまう問題がある。
Khorikov が推奨するのは、モックの使用をデータベース・外部 API・メッセージキューなど「管理外のプロセス外依存」に限定することだ。同じプロセス内のクラス同士は本物を使ってテストを組み立てる。こうすることで、内部設計を大きく変えても既存のテストが通り続ける構造が作れる。
4. テストが書きにくいなら、それは設計への警告だ
「このクラスはテストが書きにくい」と感じる原因は、テストスキルの不足より設計上の問題である場合が多い。ビジネスロジックがデータベースアクセスや外部 API 呼び出しと同居していると、テストはセットアップが複雑になり、実行も遅くなる。
本書では「関数型コア・命令的シェル」というアーキテクチャパターンが紹介されている。副作用を持たない純粋なドメインロジック(関数型コア)と、I/O を担うシェル(命令的シェル)を分離することで、コアの部分はモックなしで高速に、網羅的にテストできる。この分離は、テスト品質の問題を解決しながら同時にアーキテクチャを改善する。
DevBookPath のマップで確認する
この本の学習パス上の位置づけ・前後の読書順は、DevBookPath のグラフで辿れます。
本記事のリンクには Amazon アソシエイト等の広告が含まれる場合があります。リンク経由の購入で運営者に紹介料が支払われることがあります。
この記事を共有
この地図を共有