ClaudeとProperty-Based TestingでPythonのバグを見つける仕組み
ClaudeがProperty-Based TestingでNumPyやPandasのバグを自律発見した研究を解説します。エージェントの4段階プロセスと実際のバグ5件、評価結果を紹介します。
Property-Based Testingとは何か
Property-Based Testingは、個別の入出力例ではなく「コードが満たすべき一般的な性質」を検証するテスト手法です。たとえば「JSONのシリアライズとデシリアライズは互いに逆演算である」という性質を定義しておけば、フレームワークがその性質を破る反例を自動生成して探してくれます。ファジングに近い技術ですが、探索対象が具体的なクラッシュではなく論理的な不変条件である点が違います。
Anthropicは2026年1月14日、Claudeを使ってこの手法を自動化するエージェントの研究成果を公開しました。著者はMuhammad Maaz氏(MATS)、Liam DeVoe氏(Northeastern University)、Zac Hatfield-Dodds氏とNicholas Carlini氏(Anthropic)の4名です。研究成果は2025年のNeurIPS Deep Learning for Code Workshopで発表され、GitHubリポジトリと発見したバグの一覧サイトが公開されています。
通常のユニットテストは開発者が思いついた具体例しか検証できません。エッジケースを開発者自身が想定していなければ、実装にもテストにも同じ抜け漏れが残ります。Property-Based Testingはこの構造的な弱点を、入力ドメイン全体を対象にした自動探索で補います。
エージェントは4段階でバグを探す
Claudeのエージェントは、単一のPythonファイル・モジュール・関数のいずれかを対象として指定すると、次の手順で動きます。
- 理解: 対象コードを読み、関連ドキュメントを取得し、コードベース内での位置づけを把握する
- 性質の提案: 型注釈・docstring・関数名・コメントから、成り立つべき性質を導く
- テスト作成: Pythonのプロパティベーステストフレームワーク
Hypothesisで実際のテストコードを書く - 実行と自己反省: テストを実行し、失敗した場合は本当にバグを見つけたのか、それともテスト設計が誤っているのかを判断する
この最後の自己反省ステップが、誤検知を減らすうえで重要な役割を果たしています。ある実行例では、エージェントが最初に書いたテストは通過しましたが、自己反省の過程でテスト全体をtry-catchブロックで囲んでいたことに気づき、それを外すと本物のバグが検出されました。長時間の多段階推論を支えるため、エージェントは進行状況を記録するTODOリストも使っています。
Hypothesisによるプロパティベーステストは、次のような形で書かれます。
# example-based test(従来の例示ベース)
def test_sort():
assert my_sort([1, 3, 2]) == [1, 2, 3]
# property-based test in Hypothesis
from hypothesis import given, strategies as st
@given(st.lists(st.integers()))
def test_sort(lst):
result = my_sort(lst)
for i in range(len(result) - 1):
assert result[i] <= result[i + 1]例示ベースのテストは特定の入力しか検証しませんが、Hypothesisのテストは「ソート済みリストの定義」という性質そのものを検証し、フレームワークが反例となる入力を自動的に構築します。
100を超えるPythonパッケージで検証した結果
研究チームはNumPy・SciPy・Pandasを含む100を超える人気のPythonパッケージを対象にエージェントを実行しました。数値計算からパース処理、データベースまで幅広い領域のライブラリが含まれています。
評価は2段階で実施されました。第1段階ではClaude Opus 4.1を使い、生成された984件のバグレポートから50件を人手で抽出してレビューしたところ、56%が有効なバグ、32%が「有効かつ報告に値するバグ」でした。この結果を基に15点満点の採点基準を作り、Opus 4.1に全レポートを採点させたところ、上位スコアのレポートでは86%が有効、81%が有効かつ報告可能という水準まで精度が上がりました。
第2段階ではSonnet 4.5を使い、重要な10パッケージに対して複数回実行し、さらにSonnet 4.5自身にバグレポートの正確性と深刻度を判定させる評価エージェントを別途構築しています。高深刻度のバグについては、3名の有識者による人手評価も加えました。
| 段階 | モデル | 対象 | 有効なバグの割合 |
|---|---|---|---|
| 第1段階(全体) | モデルOpus 4.1 | 対象100超パッケージ、984件のレポートから50件を人手抽出 | 有効なバグの割合56% |
| 第1段階(上位スコア) | モデルOpus 4.1採点 | 対象15点満点ルーブリックの上位レポート | 有効なバグの割合86% |
| 第2段階 | モデルSonnet 4.5 | 対象重要10パッケージ、複数回実行 | 有効なバグの割合別途評価エージェントで判定 |
バグの有効性は開発チームによる検証を最終的な判断基準としています。研究チームは特に興味深い5件を選び、パッチ案とともに各リポジトリへ手動で報告しました。
実際に見つかった5件のバグ
報告されたバグのうち、修正の経緯が公開されているものを紹介します。
numpy.random.waldは、本来は正の値しか返さないはずのWald分布のサンプルが、まれに負の値を返す不具合でした。エージェントはWald分布の性質として「すべてのサンプルが正の値である」ことを検証するテストを書き、桁落ち(catastrophic cancellation)が原因の数値不安定な計算を突き止めました。修正後の再定式化は、従来のアルゴリズムより相対誤差が約10桁小さくなっています。パッチはNumPyのプルリクエスト#29609としてマージ済みです。
aws-lambda-powertoolsのslice_dictionary()は、イテレータをインクリメントし忘れていたため、常に最初のチャンクだけを繰り返し返す不具合でした。辞書をスライスして再構築すると元の辞書と一致するはずという性質のテストで発見され、#7246としてマージされています。
cloudformation-cli-java-pluginのitem_hash()は、インプレースの.sort()メソッド(戻り値はNone)を使っていたため、すべてのリストでhash(None)と同じ値を返していました。異なる入力は異なるハッシュ値を持つべきという性質のテストで発見され、#1106として修正案が提出されています。
tokenizersのEncodingVisualizer.calculate_label_colors()は、出力するHSLのCSS文字列の閉じ括弧が欠けており、無効な値を返していました。HSLカラーコードの正規表現に出力がマッチするかを検証するテストで発見され、#1853としてマージ済みです。
python-dateutilのeaster()は、ユリウス暦を指定した一部の年で日曜日以外の日付を返す挙動が確認されましたが、メンテナーはこれをカレンダー体系の違いによる意図した挙動と判断し、issueは無効(invalid)とされました。この事例は、コードの前提が暗黙的で複雑な意味論を含む場合、性質の導出そのものが難しくなるというエージェントの限界を示しています。
| 対象 | 症状 | 発見に使った性質 | 結果 |
|---|---|---|---|
| numpy.random.wald | 症状負の値を返すことがある | 発見に使った性質サンプルは正の値のみという性質 | 結果パッチマージ済み(#29609) |
| aws-lambda-powertools | 症状slice_dictionary()が最初のチャンクを繰り返す | 発見に使った性質スライス後の再構築が元と一致する性質 | 結果パッチマージ済み(#7246) |
| cloudformation-cli-java-plugin | 症状item_hash()が全リストで同じ値 | 発見に使った性質異なる入力は異なるハッシュという性質 | 結果パッチ提出済み(#1106) |
| tokenizers | 症状HSL文字列の閉じ括弧欠落 | 発見に使った性質出力が正規表現にマッチする性質 | 結果パッチマージ済み(#1853) |
| python-dateutil | 症状ユリウス暦でeaster()が非日曜を返す | 発見に使った性質復活祭は日曜という性質 | 結果issue無効と判定 |
パッチの自動生成はあえて対象外にしている
今回の研究では、バグの自動修正(パッチの自動生成)そのものは意図的に対象外としています。研究チームは「本研究ではパッチの自動生成には焦点を当てていない」としており、5件の代表バグに添えたパッチ案も、研究者自身がコードベースを調査して人手で作成したものです。numpy.random.waldの修正では、数値不安定な計算を突き止めたうえで、より安定した再定式化を研究者が考案してプルリクエストとして提出しています。
研究チームはこの点を明確な今後の課題として位置づけています。コードのある部分が満たすべき正しさの性質を(ほぼ)完全に指定できれば、バグの修正自体はずっと容易になるという見立てです。近い将来、LLMがメンテナーの検討に値する高品質なパッチを効果的に提案できるようになるとの見通しを示していますが、これは今回のエージェントが実証した能力ではなく、今後の研究方向として言及されているにとどまります。
この研究がテスト運用に示すもの
エージェントが自律的に性質を導き出し、テストを書き、失敗を自己検証するという一連の流れは、人間が書くテストを置き換えるものではなく補完するものとして位置づけられています。関数名やdocstring、呼び出され方といったコンテキストから「本来成り立つべき性質」を言語モデルが読み取れる点が、この手法とAIの相性の良さを支えています。E2Eテスト失敗の自動診断にも同種のMCPがあり、Cypress CloudのMCPをClaude Codeで使うがその例です。
研究チームは今後の方向性として、脆弱性の悪用に長けたLLMが増えるほど、防御側もLLMを使った先回りが必要になると指摘しています。攻撃者が同じ技術を悪用に転用できる以上、テストと修正の自動化を進めることが、脆弱性が実運用に届く前に潰す手段として重要になるという見立てです。今回の実験ではセキュリティ脆弱性そのものではなく一般的なロジックバグの発見に焦点を当てていますが、多くの脆弱性は論理的な不具合に起因するため、Property-Based Testingが早期発見の一手法になり得るとしています。
まとめ
Claudeを使ったProperty-Based Testingエージェントは、NumPy・SciPy・Pandasを含む100超のPythonパッケージから984件のバグレポートを生成し、上位スコアのレポートでは86%が有効という結果を出しました。5件の代表的なバグはすでにマージ済みまたは提出済みのパッチとして公開されています。パッチの自動生成は今回の研究では意図的に対象外とされていますが、性質の導出・テスト作成・自己検証という一連のワークフローは、既存のテスト資産を補完する実用段階に入りつつあります。GitHubリポジトリと発見したバグの全データは公開されているため、興味のある開発者は自分のプロジェクトへの適用を検討できます。
Claude Codeでこうしたエージェント的なワークフローを組む土台は、カスタムスラッシュコマンドやサブエージェントの並列設計にも共通します。Anthropicの研究チームが自律型エージェントで長時間タスクをやり切った別の事例は、フェルマーの最終定理の形式化でも読めます。