生成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