開発支援・コーディング

ミューテーションテストとは|行カバレッジ83.3%のテストが、変異の59.3%しか見つけられなかった

ミューテーションテストは何をするのかカバレッジと何が違うのか生き残った変異はどう扱うのか

行カバレッジが83.3%あるテストに、27通りの書き換えをぶつけました。

落ちたのは16通りです。残り11通りは、コードを壊しても素通りしました。

この記事の要点

  • 薄いテストは行カバレッジ83.3%
  • 同じテストの変異検出率は59.3%
  • 厚くすると91.7%と88.9%
  • 残る3通りは直しようがない

行カバレッジ83.3%のテストが、変異の59.3%しか見つけられなかった

行を通ることと、値の誤りに気づくことは別です。書き換えてみると差が出ます。

ミューテーションテストは、コードを1か所だけ書き換えてテストが落ちるかを見る手法です。実際に走らせて測りました。

対象は送料の計算です。重さ・距離・会員かどうかで料金が決まる、分岐の多い関数にしました。

javascript
function shippingFee(weight, distance, isMember) {
  let fee = 0;
  if (weight > 10) {
    fee = 800;
  } else if (weight > 5) {
    fee = 600;
  } else {
    fee = 400;
  }
  if (distance > 500) {
    fee = fee + 300;
  }
  if (isMember) {
    fee = fee - 100;
  }
  if (fee < 0) {
    fee = 0;
  }
  return fee;
}

27通りの書き換えを当てる

比較を境目こみにする、向きを変える、足し算を引き算にする、数値を1つ増やす、といった書き換えを機械的に入れました。全部で27通りです。

text
テスト            件数  殺した変異  生き残った変異  検出率
薄いテスト(2件)             2件        16通り            11通り    59.3%
厚いテスト(9件)             9件        24通り             3通り    88.9%

テスト2件の薄い版では、殺せたのは16通りです。11通りは書き換えても素通りしました。

境目の値を足して9件にすると、24通りまで殺せます。検出率は59.3%から88.9%へ上がりました。

カバレッジと並べる

text
テスト            件数  通った行  行カバレッジ  変異の検出率
薄いテスト(2件)             2件     10/12         83.3%         59.3%
厚いテスト(9件)             9件     11/12         91.7%         88.9%

薄いテストでも行カバレッジは83.3%あります。ほとんどの行を通っています。

それでも変異の検出率は59.3%です。通ってはいるが、値が違うことに気づいていない行があります。

出典もこの手法の動きを変異のそれぞれに対して、あなたのテストが走ると説明しています。

行を通っていても、値の誤りに気づくとは限らない。

薄いテスト(2件)殺した16生き残った1127通り厚いテスト(9件)24327通り−0%(0通り)27通りの変異での実測。行カバレッジは83.3%と91.7%だった。
図1 ── テストごとの変異の殺し方
出典Stryker Mutator「Mutation testing」2026-08-18 確認
Your tests are run for each mutant.
原文Stryker Mutator「Mutation testing」 この内容の有効期限2027-02-18

残った3通りは、テストを足しても殺せない

生き残りには2種類あります。テストが足りないものと、書き換えても動きが変わらないものです。

ミューテーションテストの検出率は、100%にはなりません。厚いテストで残った3通りを見ます。

text
生き残った変異の例(厚いテストでも落ちなかったもの)
  2行目 「0」→「1」(数値を1つ増やす)
  16行目 「0」→「1」(数値を1つ増やす)
  17行目 「0」→「1」(数値を1つ増やす)

生き残りは全 27通り中 3通り。

2行目は初期値の0を1に変えたものです。その直後の分岐で必ず上書きされるので、動きは変わりません。

16行目と17行目は、下限を守る分岐です。この計算では料金が最低でも300になるので、負になることがありません。

殺せない変異がある

この3通りは、テストを足しても殺せません。書き換えても動きが同じか、そこへ到達しないからです。

だから検出率は100%を目標にできません。生き残りを1つずつ見て、どちらの種類かを判断します

出典も結果の読み方を変異が殺されたか、つまり少なくとも1件のテストが落ちたか、それとも生き残ったかを教えてくれると説明しています。

種類ごとの殺しやすさ

text
変異の種類                通り数  殺した  生き残った  検出率
比較を境目こみにする                    3通り     3通り         0通り    100%
比較の向きを変える                     3通り     3通り         0通り    100%
足し算を引き算にする                    1通り     1通り         0通り    100%
引き算を足し算にする                    1通り     1通り         0通り    100%
数値を1つ増やす                     11通り     8通り         3通り     73%
数値を0にする                       8通り     8通り         0通り    100%

比較まわりはすべて殺せています。境目の値をテストに入れたためです。

残ったのは数値を1つ増やす種類だけで、11通り中3通りです。その3通りが、さきほどの到達しない箇所です。

生き残りは、数値を1つ増やす種類にだけ残った。

入れた変異 全27通りを100%とする(合計 27通り)40.7%数値を1つ増やす29.6%数値を0にする11.1%比較を境目こみ11.1%比較の向きを変える7.4%足し引きの入れ替え厚いテストで生き残った3通りは、すべて数値を1つ増やす種類のものだった。
図2 ── 変異の種類ごとの通り数
出典Stryker Mutator「Mutation testing」2026-08-18 確認
It will then tell us if a mutant was killed, meaning that at least one test failed, or if it survived.
原文Stryker Mutator「Mutation testing」 この内容の有効期限2027-02-18

変異の数だけテストが走るので、当てる範囲を絞る

実行の回数は、変異の数とテストの件数の掛け算です。全体に当てると時間がかかります。

ミューテーションテストの費用は単純です。変異の数だけ、テスト一式を回します

この計測では27通り×9件で243回の実行になりました。関数1つでこの数です。

実際のコードでは変異が数千通りになります。テスト一式が1分なら、数十時間かかる計算です。

当てる範囲を絞る

  1. 判定が集まっている部分。料金・権限・締切の計算
  2. 変更したところ。直近の差分だけに当てる
  3. 壊れると痛い部分。金額や個人情報を扱う箇所
  4. テストが薄い部分。カバレッジが低いところは先に埋める

4番目は順番の話です。行を通っていない部分には、変異を当てても全部生き残ります。先にカバレッジを埋めます。

数字の読み方

検出率そのものより、生き残った変異の一覧が使えます。どこにテストが足りないかを直接指します。

出典も関係をテストが良くなるほど、生き残る変異は少なくなるとしています。逆に言えば、生き残りがテストの穴です。

カバレッジの測り方そのものはカバレッジの記事で扱っています。行を通ることと、確かめることは別です。

先にカバレッジ、次に変異。順番を逆にすると全部生き残る。

充足 2 / 4当てる範囲を絞っている関数1つでも27通り×9件で243回の実行になる生き残った変異を1つずつ見ているテストが足りないのか、動きが変わらないのかを判断する必要がある検出率100%を目標にしている書き換えても動きが変わらない変異が残り、テストを足しても殺せないカバレッジが低いまま当てている通っていない行の変異は、すべて生き残るだけになる送料計算の関数に27通りの変異を入れた実測にもとづく。
図3 ── 始める前の点検項目
余談 この計測での注意

対象は20行ほどの関数1つです。変異の入れ方も、比較と数値と四則を機械的に置き換える単純な形にしています。実際の道具はもっと多くの種類を入れるので、通り数も検出率も変わります。ここで見せているのは、行カバレッジが高くても変異の検出率はそれより低くなること、そして殺せない変異が必ず残るという関係です。

出典Stryker Mutator「Mutation testing」2026-08-18 確認
The better your tests, the fewer mutants survive.
原文Stryker Mutator「Mutation testing」 この内容の有効期限2027-02-18

よくある質問

ミューテーションテストは何をしますか
コードを1か所だけ書き換えて、テストが落ちるかを見ます。落ちなければ、その誤りに気づけないという意味です。
カバレッジがあれば足りませんか
足りません。この計測では行カバレッジ83.3%のテストが、変異の59.3%しか見つけられませんでした。
検出率は100%にできますか
できません。この計測でも3通りが残り、いずれも書き換えても動きが変わらないものでした。
どこに使いますか
計算や判定が集まっている部分です。変異の数だけテストを回すので、全体に当てると時間がかかります。

まとめ

  • コードを壊して気づくかを見る
  • カバレッジより厳しい
  • 生き残りが足りないテストを指す
  • 100%にはできない

今日から始められること

  1. 判定が集まっている関数を1つ選ぶ
  2. 比較や数値を1か所ずつ書き換えてみる
  3. テストが落ちない書き換えを数える
  4. 落ちなかった箇所にテストを足す

実務で組んだミューテーションテストのワークフローには、値段が付きます

同じ課題を持つ会社にとって、動いている設定は「作る時間」を買えるということです。ServiceDockは自作のワークフローやテンプレートを出品できるマーケットプレイスです。手数料や出品の流れは出品者向けページにまとまっています。

出品の仕組みを見る