ユニットテストをAIに書かせると、通るしカバレッジも出ます。それでも怖いです。緑なのに、実装を少し壊しても落ちないテストが混ざっていないか、目視では追いきれません。
最近Software Designの紹介を読んで、今走っているプロジェクトにもミューテーションテストを入れました。コードを少し壊して、いまあるテストが気づくかを見ます。ツールはmutmut 2.5.1です。
対象を絞った理由
HTTPや設定までmutateすると、待つ時間とノイズだけが増えました。二重送信や受付後のCRM失敗は、mutationではなくシナリオテスト側です。mutationには「遷移のテストが甘くないか」だけを見させました。
| シリーズ側の関心 | mutation対象 |
|---|---|
| 履歴の状態遷移 | 遷移モジュール |
| 確認用JSONの読み書き・判定 | ポーリング判定 |
| 保存・更新前のガード | guard |
| ファイル名ルール | filename policy |
| Widget/HMAC入口/handler | 対象外 |
遷移条件やguardが壊れてテストが気づくかはmutationです。二重送信や部分成功の順序、見たPDFと保存PDFの食い違い、確認用が競合で上書きしないかはシナリオ側です。
mutateした範囲
外部I/Oがないモジュールに限定し、回すテストもそこに絞ります。設定の正本は setup.cfg の [mutmut] でした。
[mutmut]
paths_to_mutate=
src/app/domain/job_history.py,
src/app/domain/polling.py,
src/app/services/history_guard.py,
src/app/services/filename_policy.py
runner=.venv/bin/python -m pytest
tests/unit/test_job_history_transitions.py
tests/unit/test_polling.py
tests/unit/test_history_guard.py
tests/unit/test_filename_policy.py
遷移してよいケースといけないケースの両方を厚く書きます。正常系だけの薄いテストの上にmutationを置くと、survivedが並ぶ以外ほぼ何も出ません。
survivedが出たとき
落としたいものはテストを足します。見た目だけ破壊で意味が同じならpragmaか台帳です。殺せるがスイートが良くならないものも台帳に理由を書きます。全部を「テスト不足」に押し込むのがいちばん危ないです🙇。
状態enumのメンバはpragmaで、専用テストで値を固定しました。禁止文字ループの短縮は、別置換で実害がないので台帳です。エラーメッセージの部分一致だけだと、キー名のtypoを殺せないことがあるので、キー自体を見るassertを足しました。
# 甘い
assert "next_check" in err.msg
# get("next_check_atx") がsurvivedになることがある
点数と運用
total = killed + survived + suspicious
score = 100.0 * killed / total
mutateした範囲だけの点数です。ゲートは85%です。手元のcacheではkilled 242、survived 22、suspicious 1で、だいたい91.3%でした。
普段は表示だけです。夜にまとめて回す前提で、毎回のPR必須にはしていません🙇。壊すたびにテストが走るので重いです。
make test/mutation
.venv/bin/python -m mutmut results
.venv/bin/python -m mutmut show <id>
カバレッジとの違い
カバレッジは「通ったか」だけです。mutationは「壊したら落ちるか」です。見た目は壊れて意味は同じequivalentは、完全自動判定が難しいです。survivedにはテスト不足と等価が混ざります。なので「殺しても得しない」ノイズもあります。だから範囲を先に決める必要性があります。
AIが量産した通るだけのテストの上に、全ファイルmutateを載せても、ノイズ以外はほぼ返ってきません。守りたい遷移を厚くしてから噛ませた方がいいです🙏。自分にとっては、副作用の状態機械をAI製ユニットテストだけに信じないための手段でした。
参考
- Yue Jia, Mark Harman. An Analysis and Survey of the Development of Mutation Testing. IEEE TSE, 2011. https://doi.org/10.1109/TSE.2010.62
- Goran Petrović, Marko Ivanković. State of Mutation Testing at Google. ICSE SEIP, 2018. https://research.google/pubs/state-of-mutation-testing-at-google/
- Petrović et al. Practical Mutation Testing at Scale. https://ar5iv.labs.arxiv.org/html/2102.11378
- mutmut documentation. https://mutmut.readthedocs.io/en/latest/
- Anders Hovmöller. Mutation testing in practice. https://medium.com/@boxed/mutation-testing-in-practice-bc56f9e5b591
- PIT. https://pitest.org/