生成AIが書く自動テストは複雑なコードに耐えられるのか
最近、生成AIネタばっかり書いてる気がする。
ふと、どれだけ複雑なコードに生成AIが耐えられるのか実験したくなりやってみた。
何をするのか
- 複雑なコードを書いて自動テストを生成AIに実装させる
- 自動生成されたテストケース数とテスト通過数を観察する
モデル
Gpt-4o
実験に使うコード
今回は事前に用意した下の複雑なコードを使う
可能な限りパスケースを用意した中々にヤバめのコードである
def get_diff_hash(a_value, b_value, a_name, b_name, flg) if a_name.nil? raise ArgumentError, 'a_name cannot be nil' end if b_name.nil? raise ArgumentError, 'b_name cannot be nil' end unless ["after", "before"].include?(flg) raise ArgumentError, 'flg must be either "after" or "before":' + flg end if flg == 'after' if (a_name == 'specific_a_name' && b_name == 'specific_b_name') || (b_name == "fuga" && a_name == 'hoge') if a_value && b_value return { diff: has_diff?(a_value, b_value), value: a_value - b_value, name: 'specific_after_name_1' } end return { diff: has_diff?(a_value, b_value), value: a_value, name: 'specific_after_name_2' } if a_value && !b_value return { diff: has_diff?(a_value, b_value), value: nil, name: 'specific_after_name_3' } if !a_value && b_value return { diff: has_diff?(a_value, b_value), value: nil, name: 'specific_after_name_4' } if !a_value && !b_value end if a_value && b_value return { diff: has_diff?(a_value, b_value), value: a_value - b_value, name: a_name } end return { diff: has_diff?(a_value, b_value), value: a_value, name: a_name } if a_value && !b_value return { diff: has_diff?(a_value, b_value), value: nil, name: a_name } if !a_value && b_value return { diff: has_diff?(a_value, b_value), value: nil, name: a_name } if !a_value && !b_value end if flg == 'before' if (a_name == 'specific_a_name_2' && b_name == 'specific_b_name_2') || (b_name == "hoge" && a_name == 'fuga') if a_value && b_value return { diff: has_diff?(a_value, b_value), value: b_value - a_value, name: 'specific_before_name_1' } end return { diff: has_diff?(a_value, b_value), value: b_value, name: 'specific_before_name_2' } if a_value && !b_value return { diff: has_diff?(a_value, b_value), value: nil, name: 'specific_before_name_3' } if !a_value && b_value return { diff: has_diff?(a_value, b_value), value: nil, name: 'specific_before_name_4' } if !a_value && !b_value end if a_value && b_value return { diff: has_diff?(a_value, b_value), value: b_value - a_value, name: a_name } end return { diff: has_diff?(a_value, b_value), value: b_value, name: a_name } if a_value && !b_value return { diff: has_diff?(a_value, b_value), value: nil, name: a_name } if !a_value && b_value return { diff: has_diff?(a_value, b_value), value: nil, name: a_name } if !a_value && !b_value end end def has_diff?(a_value, b_value) a_value.to_s == b_value.to_s end
プロンプト
今回の実験で生成AIに投げるプロンプト
sample_code.rbのテストを書いてください。 以前、実装したテストケースは忘れて1から考えてください。 可能な限り条件を網羅してください。 日本語で記述をお願いします。 実装したテストコードは、直接反映させるのではなくマウスからコピペできる形で出力してください。
期待するテストケースの数
自分ならこれくらい書くだろうというテストケースの数を期待値として設定
合計29ケース
- 異常系 x 3
- afterのパス x 13
(a_name == 'specific_a_name' && b_name == 'specific_b_name')のパターン(b_name == "fuga" && a_name == 'hoge')のパターン- a_nameとb_nameが上記以外のパターン
- a_nameとb_nameが存在するが差分なしのパターン
- beforeのパス x 13
(a_name == 'specific_a_name_2' && b_name == 'specific_b_name_2')のパターン(b_name == "hoge" && a_name == 'fuga')のパターン- a_nameとb_nameが上記以外のパターン
- a_nameとb_nameが存在するが差分なしのパターン
結果
- 異常系は拾ってくれるんだけど、afterのパスとbeforeのパスが漏れていた
| 回数 | テストケースの数 | テスト失敗数 | 漏れテストケース数 |
|---|---|---|---|
| 1回目 | 10 | 2 | 19 |
| 2回目 | 11 | 2 | 18 |
| 3回目 | 13 | 4 | 16 |
| 4回目 | 11 | 4 | 18 |
| 5回目 | 13 | 4 | 16 |
| 6回目 | 13 | 4 | 16 |
| 7回目 | 13 | 4 | 16 |
| 8回目 | 13 | 4 | 16 |
| 9回目 | 13 | 4 | 16 |
| 10回目 | 13 | 4 | 16 |