ナレッジNEW
【連載】なにそれ?あなたの知らないテストの言葉(第2回):ミューテーションテスト(Mutation testing)

マンガ連載:ミューテーションテスト(Mutation testing)とは

解説:ミューテーションテスト(Mutation testing)とは
このマンガ連載では普段目にすることが少ない「なにそれ」という用語をピックアップして解説します。
第2回は「ミューテーションテスト(Mutation testing)」です。なお2025年3月現在、ISTQB(International Software Testing Qualifications Board)の用語に記載はありません。
ミューテーションテストは、プログラムに小さな変更(ミューテーション)を行い、それを既存のテストで検出(kill)できるかどうかを測定することで、テストの有効性を評価する技法の一つです。
ミューテーションによって作られる変更は欠陥をシミュレートしたものと言えます。作り込まれた欠陥を検出できた場合は、例えばリファクタリングでその種類の欠陥が埋め込まれたとしても、テストで見つけられるであろうことが言えます。検出されない場合はその種類の欠陥に対してテストを行っていない、またはテストが効果的ではないことを示しています。
ミューテーションテストの主目的はテストケースを評価することです。コードやプロダクト自体の品質を検証できるわけではないので注意しましょう。
ミューテーションの種類
ステートメントミューテーション
コード内のステートメント(文)のコピーや削除、並び順を入れ替えるミューテーションです。
プログラムの正しい実行において、それぞれのステートメントには重要な意味がありますし、並び順にも意味があります。これらをうっかり間違ってしまった場合にその欠陥をテストで検出できるかが分かります。
if文でelseのセクションを削除してしまう、といった例が挙げられます。
バリューミューテーション
コード内のパラメーターや定数を変更するミューテーションです。
これによって、誤って異なるパラメーターや定数にしてしまった場合にテストで検出できるかが分かります。または計算結果等が大き過ぎる値、小さ過ぎる値になってしまった場合に予期せぬ問題の発生を検出できる可能性もあります。
デシジョンミューテーション
マンガで例示した部分です。論理演算子(&&など)、比較演算子(==など)、算術演算子(+など)を変更するミューテーションです。
これより、主に分岐部分の問題をテストで検出できるかが分かります。
ミューテーションテストのメリット
テストカバレッジの強化
ミューテーションテストを行い見つけられなかった欠陥を分析することで、不足している、または効果的ではないテストケースが分かります。これらの追加や修正でテストカバレッジを強化できます。
また開発の初期段階で適用することにより、早い段階でテストの問題に気付き、以後のテストアプローチを効果的にすることにも一役買うことができます。
ミューテーションテストでテストの不足が分かりますが、全てに対応しようとするとテストの修正コストや以後のメンテナンスのコストがかかります。どこまで対応するか方針を決めることをお勧めします。
コードカバレッジでは気付かない問題に気付ける可能性がある
コードカバレッジでは、テストケースでカバーされているコードの割合が分かります。ですがマンガ内で示したようにテストが効果的か(欠陥を見つけられるか)は分かりません。ミューテーションテストでは実際に欠陥を作りそれをテストで見つけられるかを検証します。これによって新たな問題(>=を==と書いていたなど)に気付ける可能性があります。
ミューテーションテストのデメリット
時間がかかる
メリットを打ち消すほどのデメリットであり、現場での実運用を妨げる要因です。
ミューテーションテストでは、一つの文からさまざまなミュータントを生み出します。その生成された各ミュータントに対して既存のテストスイート全体を実行します。これによりシステムが大規模になるほど実行時間が非常に長くなっていきます。
Googleではこの問題に対してdiff部分に絞るといったアプローチをしています。これがどういったものかは後述します。
結果が変わらない変更がある
変更が行われても、動作が元のプログラムと変わらない場合があります。例えば、正か負かを判定するようなプログラムで、-1を-2にしたとしても戻り値としては負であることに変わりありません。動作は変わらないため、テストが正しくてもミュータントをkillできません。
これら結果の検証は手動で行う必要があるため、作業に時間がかかってしまいます。
正しいテストであってもミューテーションスコア(テストでどれだけ欠陥を検知できるかのスコア)が下がってしまうため、テストの有効性を反映しないスコアとなります。
Googleでのミューテーションテストの取り組み
ミューテーションテストのデメリットとして時間がかかることを挙げました。これに対してGoogleでは以下のような取り組みをしています。簡単に列挙します。
- diff(変更された差分)に対してのみミュータントを作成する
- ステートメントカバレッジ(C0カバレッジ)を利用して、実際にテストされている行だけをミューテーションテストの対象とする
- log出力やimport文などテストする意味が薄い部分を自動的に判断して、そこのミュータントは作成しない(論文内ではAridと表現)
- 1行1ミュータント。どんな種類の変更をするかはランダムで選ぶ
- レビューのコード表示の中にミューテーションテストの結果(生き残ったミュータント)を出す。開発者がこのフィードバックが有用だったかをワンクリックで返せるようにしている
ミュータントは実際の欠陥の代替として妥当か?
ミューテーションテストでさまざまな欠陥を自動的に作成し検出できるか確認をするけれど、その行為が果たして実際の欠陥を見つけられることになるのか――つまりテストスイートのミューテーションスコアが高いことが実際の欠陥を検出しやすいことと同義なのかについては以下の論文があります。
オープンソースを対象に、バグ修正コミットから357件の実際の欠陥を特定し、それらの修正前バージョンと修正後バージョンを用意。開発者が書いた既存のテスト(修正前バージョン、修正後バージョン)を用意し、実際の欠陥を検出できているテストケースを抽出します。修正後バージョンに対してミューテーションテストを行い、各テストのミューテーションスコア(テストでどれだけ変更を検出できたか)を計算し、実際のバグ検知率との相関を調査しています。
実際の欠陥357件のうち73%が、ミュータントによって再現できる(テストが実際の欠陥を検知するとき、対応するミュータントも少なくとも一つ以上検知される)ことが確認されました。これを論文中では the coupling effectと呼んでおり、つまり73%の実際の欠陥は一つ以上のミュータントと結び付いた形で検知されるという結果です。
これにより、テストがミュータントをどれだけ検知できるか(ミューテーションスコア)と、実際の欠陥をどれだけ検知できるかには、中~強程度の正の相関があることが示されています。よって、ミューテーションテストは実際の欠陥検出についての有効な近似指標に成り得ると結論付けています。
マンガでわかるソフトウェアテスト入門
よろしければこちらもご覧ください。
この記事は面白かったですか?
今後の改善の参考にさせていただきます!