行カバレッジが83.3%あるテストに、27通りの書き換えをぶつけました。
落ちたのは16通りです。残り11通りは、コードを壊しても素通りしました。
行を通ることと、値の誤りに気づくことは別です。書き換えてみると差が出ます。
ミューテーションテストは、コードを1か所だけ書き換えてテストが落ちるかを見る手法です。実際に走らせて測りました。
対象は送料の計算です。重さ・距離・会員かどうかで料金が決まる、分岐の多い関数にしました。
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;
}
比較を境目こみにする、向きを変える、足し算を引き算にする、数値を1つ増やす、といった書き換えを機械的に入れました。全部で27通りです。
テスト 件数 殺した変異 生き残った変異 検出率 薄いテスト(2件) 2件 16通り 11通り 59.3% 厚いテスト(9件) 9件 24通り 3通り 88.9%
テスト2件の薄い版では、殺せたのは16通りです。11通りは書き換えても素通りしました。
境目の値を足して9件にすると、24通りまで殺せます。検出率は59.3%から88.9%へ上がりました。
テスト 件数 通った行 行カバレッジ 変異の検出率 薄いテスト(2件) 2件 10/12 83.3% 59.3% 厚いテスト(9件) 9件 11/12 91.7% 88.9%
薄いテストでも行カバレッジは83.3%あります。ほとんどの行を通っています。
それでも変異の検出率は59.3%です。通ってはいるが、値が違うことに気づいていない行があります。
出典もこの手法の動きを変異のそれぞれに対して、あなたのテストが走ると説明しています。
行を通っていても、値の誤りに気づくとは限らない。
生き残りには2種類あります。テストが足りないものと、書き換えても動きが変わらないものです。
ミューテーションテストの検出率は、100%にはなりません。厚いテストで残った3通りを見ます。
生き残った変異の例(厚いテストでも落ちなかったもの) 2行目 「0」→「1」(数値を1つ増やす) 16行目 「0」→「1」(数値を1つ増やす) 17行目 「0」→「1」(数値を1つ増やす) 生き残りは全 27通り中 3通り。
2行目は初期値の0を1に変えたものです。その直後の分岐で必ず上書きされるので、動きは変わりません。
16行目と17行目は、下限を守る分岐です。この計算では料金が最低でも300になるので、負になることがありません。
この3通りは、テストを足しても殺せません。書き換えても動きが同じか、そこへ到達しないからです。
だから検出率は100%を目標にできません。生き残りを1つずつ見て、どちらの種類かを判断します。
出典も結果の読み方を変異が殺されたか、つまり少なくとも1件のテストが落ちたか、それとも生き残ったかを教えてくれると説明しています。
変異の種類 通り数 殺した 生き残った 検出率 比較を境目こみにする 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つ増やす種類にだけ残った。
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分なら、数十時間かかる計算です。
4番目は順番の話です。行を通っていない部分には、変異を当てても全部生き残ります。先にカバレッジを埋めます。
検出率そのものより、生き残った変異の一覧が使えます。どこにテストが足りないかを直接指します。
出典も関係をテストが良くなるほど、生き残る変異は少なくなるとしています。逆に言えば、生き残りがテストの穴です。
カバレッジの測り方そのものはカバレッジの記事で扱っています。行を通ることと、確かめることは別です。
先にカバレッジ、次に変異。順番を逆にすると全部生き残る。
対象は20行ほどの関数1つです。変異の入れ方も、比較と数値と四則を機械的に置き換える単純な形にしています。実際の道具はもっと多くの種類を入れるので、通り数も検出率も変わります。ここで見せているのは、行カバレッジが高くても変異の検出率はそれより低くなること、そして殺せない変異が必ず残るという関係です。
The better your tests, the fewer mutants survive.原文Stryker Mutator「Mutation testing」 この内容の有効期限2027-02-18
同じ課題を持つ会社にとって、動いている設定は「作る時間」を買えるということです。ServiceDockは自作のワークフローやテンプレートを出品できるマーケットプレイスです。手数料や出品の流れは出品者向けページにまとまっています。
出品の仕組みを見る