コンテンツにスキップ

ミューテーションテストツール「hoimin」の実装

2026-10-07 公開

ミューテーションテストツールをvibe codingで実装した。その名は「hoimin」。

なぜ実装したのか

Pythonコード向けのミューテーションテストツールとしてmutmutやCosmic Rayが存在する。 実際、僕もロバストPythonでmutmutを紹介されているのを読んでミューテーションテストの存在を知ったのであった。 実際にmutmutやCosmic Rayを使ったことがあればわかると思うが、単純に生成されるミュータントの数が多すぎるのだ。 そのミュータントも駆除すべきものなのか、等価ミュータントなのかもわからない。 ロバストPythonでも言及されている通り、コストパフォーマンスが悪い手法であった。

確かに、ミューテーションテストは「やりたいことはわかるけれども面倒なテスト」であった。 しかし、生成AIやAIエージェントがそのコストを肩代わりしてくれるようになった。 お手本となるテストが既に存在して、ミュータントの駆除という明確なゴールもある。 ミューテーションテストはAIエージェントの時代に花開いた手法なのである。

それならばと、AIエージェントにmutmutやCosmic Rayでミューテーションテストを依頼すると、高確率でPCがハングするのである。 ミュータントを一気に駆除せんがために並列にテストを実行して、メモリが枯渇する。 ミュータントを大量に生成するので、ディスクが枯渇する。 ミューテーションテストはAIエージェントにやってほしいのに、既存のミューテーションテストツールはAIエージェントの手に負えない代物なのであった。 また、mutmutやCosmic Rayはファイルベースで設定するので逐一設定ファイルを書き換えなければならない。トークンの無駄である。

hoiminは上記のような弱点を克服したツール、つまりAIエージェントが扱いやすいツールを指向している。 具体的には、実行時にPCがハングしないようにメモリ使用量やディスク使用量を制限できる、生成するミュータントの数を指定できる、CLIベースで指定できる、といった機能を備えている。 また、mutmutはWindowsで動作しない問題もあり、WindowsやmacOS、Linuxで動作することも目標に据えた。 特定のテストツールに依存しないことも意識している。 pytestはもちろんのこと、hypothesisベースのテストでも実行できる(mutmutはhypothesisベースのテストが苦手である)。 つまり、pytestなどの自動テスト以外にも、mypyもテストツールとして利用できる。 型チェッカに合わせて、型アノテーションをミューテーションさせる機能もある。 効果のほどはまだ未検証だが、listやtupleのような型アノテーションをSequenceなどに緩和できる箇所を発見できるかもしれない。

要は、AIエージェントに安心してミューテーションテストをやってもらうために、hoiminを実装したのである。

技術選定

メモリ使用量やディスク使用量を制御するとなるとOSの機能を使わざるを得ない。 よって、プログラミング言語はシステムプログラミングに適したものを選択することになり、Rustを選択した。 自分の知識量や力量ならばRustなど使いこなせないが、それはvibe codingの時代である。 目標からずれないようにAIエージェントを制御しつつ、実装を指示し続けた。

crateとしてhoimin-coreとhoimin-cliに分離してある。 hoimin-coreは状態遷移、結果分類、リソース管理、終了判断、hoimin-cliは構文解析、テスト実行、OS別のリソース制御、レポートを担っている。 この設計はSans-IOの考え方を借用するように指示した結果である。 また、Leanによる形式証明も行っている。Leanもまた自分の知識量や力量ならば使いこなせないが、vibe codingでそれをごまかしている。 Rustコードに対してもミューテーションテストを実施したが、ディスクが一瞬で枯渇した。 Rustコード向けhoiminもほしいところである。

展望

Rust向けhoiminやTypeScript向けhoiminがあると便利そうではある。 現在の設計ではhoimin-cliにPython特有の実装が多いので、まずはcrateを分離して共通crateと言語特化crateに分けなければならない。 元々、AIエージェントに使ってもらうツールなのでドキュメントの類はそっけないが、ツールを探している人間の開発者のためにまとまったドキュメントがあってもいいかもしれない。 もはや、人間がマニュアルを読む時代ではないのかもしれないが。