1 ポイント 投稿者 GN⁺ 2024-02-25 | 1件のコメント | WhatsAppで共有

Metaの新しいLLMベースのテスト生成器は、開発の未来を垣間見る機会

  • Metaは「Automated Unit Test Improvement using Large Language Models at Meta」という論文を発表。
  • この論文は、AIを使って開発速度を高め、ソフトウェアのバグを減らす方法を示している。
  • LLMを開発者のワークフローに統合しつつ、現在のコードカバレッジを改善する正確で完全なソフトウェア改善案を提案する。

主なポイント

  • TestGen-LLMは「Assured LLM-based Software Engineering」(Assured LLMSE)アプローチを使用。
  • 複数のLLM、プロンプト、ハイパーパラメータを用いてコード改善案を生成し、最良の改善案を選ぶアンサンブル手法を採用。
  • TestGen-LLMは、既存の人間が書いたテストを改善するために特別に設計されている。

統計

  • InstagramのReelsおよびStories製品評価では、TestGen-LLMが生成したテストケースの75%が正常にビルドされ、57%が安定して通過し、25%がカバレッジを増加させた。
  • TestGen-LLMは適用されたすべてのクラスの10%を改善でき、開発者は73%のテスト改善案を受け入れて本番環境に適用した。
  • MetaエンジニアがInstagramのテストカバレッジを増やすためにテストを生成する「test-a-thon」では、TestGen-LLMのテストが追加したコード行数の中央値は2.5だった。

実践的なインサイト

  • LLMを使って開発生産性とソフトウェア信頼性を効率的に高められる好例。
  • LLMの真の価値は、予想外のエッジケースを見つけて捉えることにある。
  • LLMを本番利用するには、オーケストレーション、パイプライン、処理が必要。

TestGen-LLMの動作方式

  • TestGen-LLMは、Metaの社内LLMによって生成された候補ソリューションに一連のセマンティックフィルタを適用し、最も価値の高いテストだけを保持する。
  • フィルタ1: ビルド可能性、フィルタ2: 実行(テスト通過可否)、フィルタ3: 不安定さ、フィルタ4: カバレッジ改善。
  • こうした処理フィルタによって、テストスイートの改善を保証する。

結論

  • この論文は、多くの開発者がすでにLLMを使っている中で、ソフトウェア信頼性の領域におけるLLMの進展を追う良い方法となっている。
  • LLMは今後、ますます複雑なソフトウェアシステムでバグを見つけ、テストできるようになるだろう。

GN⁺の見解

  • この記事は、人工知能がソフトウェア開発の未来にどのような影響を与えうるかについて興味深い洞察を提供する。
  • TestGen-LLMのようなツールは、開発者の作業を自動化し、効率性を高めるうえで大いに役立つ可能性がある。
  • こうした技術の進歩は、ソフトウェア開発の複雑さを減らし、品質を向上させ、開発者の時間を節約する方向へ進んでいる。

1件のコメント

 
GN⁺ 2024-02-25
Hacker News のコメント
  • LLMを実装よりも先にテストコード作成へ使おうとする流れは興味深い
    TDDをやりすぎたせいかもしれないが、テストとはシステムがどう動作すべきかを説明するものであり、この部分は人間が定義すべきだと思っている。コードはテストが作ったガードレールの中に収まるべきもの
    ただし、LLMは仕様が不足している領域を指摘する助けにはなり得る。仕様が十分でない部分について単体テストを提案させる、というのがここで起きていることなのかもしれない
    LLM以前にも、テストをすべて書いておけば、猿がタイプライターでアプリケーションを作れるのではないか、と時々考えていた

    • レガシーコードベースでは、よく**特性化テスト(characterisation tests)**を作る
      人がコードはこう動くべきだと信じていることではなく、現在のコードベースが実際にどう動作しているかを定義するテスト
      これにより、回帰を最小限に抑えながら書き直し、リファクタリング、再設計ができる。多くのレガシーコードの問題は、意図された動作を誰も理解していないことにあり、時にはユーザーでさえ実際の動作とは違う形で動くべきだと信じている
      だから、明示的に望んだ変更でない限り、動作を変えないことが最も重要になる
    • すでに知っているかもしれないが、**プロパティベーステスト(property-based testing)**を思い出してみる価値がある。Hypothesisがたぶん最も広めたものでおすすめもできるが、唯一のアプローチでも最高品質の実装でもない。HaskellのQuickCheckも、HNで見かけるくらい大きくなった時期があった
      基本的な考え方は、完全な閉形式の証明体系よりは弱いコード動作の命題を「プロパティ」として表現し、本質的に確率的な限界の中で検証すること
      代表例は文字列の反転。文字列を2回反転すれば、通常は入力が返ってくるはずだ。コード1行で、時間と電力が許す限り、奇妙なUnicodeの境界ケースも確認できる
      例は些細に見えるが、後にPyTorchになった自動微分やカーネル作業をしていたCUDAの達人たちがこの方法を非常にうまく使い、半分の労力とコストでコード信頼性を5倍ほど得ているのを見た
      常にうまく合うわけではないが、はまれば素晴らしいし、LLMはゼロから始めるよりもHypothesisの事例にかなり近づけそうに見える
    • 実装コードを書くのは、アプリケーションが実際にすべきことを作る作業なので、はるかに楽しく興味深い
      逆にテストを書くときは、極端に冗長で制約の多い言語でアプリケーションがすべきことを説明しなければならず、いくつかの美化されたif/elseを入れるために数十行、あるいは数百行の設定コードを書く必要がある
      C++やJavaのような言語では単体テストは退屈さでできているので、その仕事をLLMに任せたいという本能が生まれるのはまったく不思議ではない
    • 多くのエンジニアが実際にはテストをうまくやっていないからかもしれない
      数日間コードを書いた後で、やむを得ずシステムが動くことを「証明」するテストをいくつか後から書くエンジニアをたくさん見てきた。カバレッジは低く、たいてい壊れやすい
      そういう考え方や働き方をするエンジニアにとって、この種のシステムは天からの贈り物に見えるだろう
      テストを先に書くと遅いと言って禁止したマネージャーもいた。幸い派遣の立場だったので「私の上司に言ってください」と言って無視できたが、おそらく上のエンジニアたちと同じ考えだったのだろう
      別の見方をすれば、ほとんどの開発者はドキュメントが嫌いだ。コードから優れたドキュメントを書いてくれるAIがあれば喜ぶだろう。そしてそういう開発者にとっては、自分が書かなくて済むドキュメントこそ優れたドキュメントなのだ
    • AI以外でも、テストコードの扱われ方を見ると同じように感じる
      テストコードはしばしば優先度の低いコードとして扱われ、よりジュニアなエンジニアに任されるが、望ましい方向とは真逆に見える
  • 全体を全部検討したいわけではないが、ある部分は特に大きく外しているように思う
    元論文は公開直後にざっと読んだだけで、今は流し読みしているところなので記憶は曖昧だという前提がある
    ブログでは、MetaのTestGen-LLMのテストの大半は追加で2.5行しかカバーしなかったが、ある1つのテストは1326行をカバーし、その1つのテストの価値は「指数関数的に大きく」、LLMが積極的に枠の外で考えて予期しない境界ケースを捉える価値が大きい、と書いていた
    しかし「指数関数的に価値が大きい」という表現の時点で、でたらめ検知器が鳴るべきだ。論文を見ると、著者たちはこの1326行のカバレッジを大当たりした単一のテストとして説明しており、単一のTestGen-LLMテストに期待できる現実的な追加ラインカバレッジは中央値2.5行だと言っている
    著者たちは「予期しない境界ケース」や「枠の外で考えること」には言及していない。むしろ、ひどいswitch文の1分岐に触れたか、コードカバレッジの計算方法の偶然かもしれない例外的なケースとして提示している
    「定性的結果」セクションでも、これをさらに掘り下げていない点が目に付く。不正確な解説は誰の役にも立たない。インターネットには、読んだふりをしたものを理解したふりをする人がすでに多すぎる

    • 書いた本人だが、論文の著者たちが「予期しない境界ケース」や「枠の外で考えること」を言った、と主張するつもりではなかった
      一部の解釈は自分の意見だという点がより明確になるよう、記事を修正した
      この記事は論文の要約というより、論文の結果が意味するものについての論評に近い。いずれにせよHacker Newsは議論のための場なので
      それでも「指数関数的に価値が大きい」という部分は、今でも正しいと思っている。LLMがテストカバレッジの面で偶然「大当たり」できるという点こそが、価値の核心だ
      さまざまな組み合わせを試し続け、論文のように大当たりを1つ引くだけでも、チームにとっては非常に価値がある。人間が直接書くには明確でなかったか、退屈すぎたテストかもしれない
      Big Techのコードベース(F/G)で、何をテストすべきかはすでに分かっているのに、「どうテストするか」を突き止めるだけにあまりにも多くの時間を費やしてきた立場からすると、その価値は大きいと思う
    • Metaのコード生産インセンティブは全般的に間違っている
      このチームもコード行数とdiff数を中心に追い立てられているのは明らかだ。結局、デバッグしにくいコードの山をもう1つ作るコード生成ツールになるだけだ
  • 良いテストは難しく、カバレッジは無条件に良いものではない
    テストを書きすぎてプログラムを固めてしまい、実質的に変更検知プログラムを作ってしまいがちです。「何か変えましたね、すべてのテストが壊れました。大丈夫、今度はLLMにまた生成させればいいんです!100%カバレッジ!驚きですね!進歩ですね!」という具合になります

    • 同意します。良いテストは良いコードより桁違いに難しいです
    • 「変更検知プログラム」という見方は興味深いです。なぜそれが悪いのか気になります
      私にとっては、その変更が意図したものか確認する機会です。それがなければ、プログラムがやるべきことをやっているとどうやって分かるのでしょうか?
    • カバレッジのないコードにはひどいテストがある、ということは確実に分かります
      それ以外については、別の5人が良いと思ったテストを読まなければなりません。私たちはみなテストを書くのが下手で、それぞれ自分のやり方でやっているだけです
    • ある職場にはWeb Componentsのテストがあり、期待されるDOMのスナップショットをコミットして、コンポーネントがそれを出力するか検証していました
      その後、あらゆる変更で開発者は自然に再生成ボタンを押し、全部コミットするようになりました。diffは豊富でしたが、シグナルは疑わしいものでした
    • 核心はロングテールのケースにあります
  • 半導体業界、とくに計算リソグラフィのようにテスト駆動設計が標準になっている場所で働いた後だと、あまり納得できません
    本番コードより常に先にテストを書かなければならない、という意味ではありません。しかしテストはコードベースの他の部分と同じくコードの一部であり、必ずテスト対象のコードと一緒に書かれるべきです
    テストで最も重要なのは、開発者の意図を示すことです。テストスイートは、そのコードがどう使われるべきか、何をするのか、何をしないのか、何のために書かれたのかを示します
    そうすれば、他の開発者がそのコードを使ったり修正したりするとき、コードベースの中でシャーロック・ホームズのように手がかりを探し回る必要がありません
    テストが物語を語っていないなら、そのテストの書き方は間違っています
    コンピュータが心を読んで意図をよりよく理解できるようになるまでは、AI/LLMベースの生成器がこの仕事を代わりにこなすことはできません
    もちろん、テストスイートの唯一の目的がコミット前チェックで緑のチェックマークをもらい、見栄えのするカバレッジ数値を見せることなら、AIで生産性を2倍にできるでしょう
    自動コード生成器は、悪いコードを光の速さでより大量に書く手助けをしてくれるでしょう。ボイラープレートが多くてコードが肥大し理解しにくいと誰かが不満を言ったら、AIで処理しろと言えばいいのです。あなたには効いたのですから
    本当に開発の未来はそう見えますが、私が期待する未来ではありません

    • ほぼすべて同意しますが、この種のテストにも居場所はあると思います
      あなたが説明しているのは、コードの「核心」をテストする側のように見えます。ドキュメント化、検証、安定性の一部を兼ねるテストです
      ファジングのような別のテストは、まったく異なる価値を提供します。AIベースのテストは、分布の裾のほう、つまり人間のエネルギーと時間が足りず放置される、価値は低いが多数あるテストを狙う領域を占め得ると思います
      現在のAIツールの状態もそう見ています。認知補助ツールです
      この研究の方向性が今後数年でかなり実を結ばないとしたら、むしろ驚くと思います
  • 論文自体が投稿されたときに書いた内容を少し整えて再引用します。彼らの文章は統計を誤って表現しています
    https://news.ycombinator.com/item?id=39406726
    要旨は実際の論文内容と合っていません。要約は、テストケース基準の割合のように「75%が正しくビルドされ、57%が安定して通過し、25%がカバレッジを増やした」と読めるものになっています
    実際のレポートはテストクラス基準で述べており、各クラスには1つ以上のテストケースがあります
    「75%のテストクラスには正しくビルドされる新しいテストケースが少なくとも1つあった」「57%のテストクラスには正しくビルドされ安定して通過するテストケースが少なくとも1つあった」「25%のテストクラスには、同じビルドターゲットの他のテストクラスと比べて、ビルドされ通過しラインカバレッジを増やすテストケースが少なくとも1つあった」という意味です
    この2つはまったく別の文です。各テストクラス拡張の試行にはテストケース生成の試行が複数回含まれ得るため、テストケースあたりの成功率は通常、テストクラスあたりの成功率よりはるかに低い、という脚注まであります
    ところが結論では、要旨と同じようにまた結果を誤って表現しています。実験モードでTestGen-LLMを使うとテストケースあたりの成功率は25%で、ラインカバレッジ要件を緩めてビルドと通過だけを求めれば成功率は57%に上がる、と書いています

  • 今後このひどいLLMレガシーコードを保守する人たちに感情移入してしまいます
    見苦しいものになるでしょう

    • 当然、それを保守するLLMを使うことになるでしょう
    • それならLLMは仕事をなくしているというより、作っていることになります。ただし、あまり面白い仕事ではなさそうです
    • エンタープライズ式コードより悪いとは思いません
      むしろかなり似て見えるかもしれず、コメントやドキュメントはより充実し、積極的に間違う可能性は低いかもしれません
    • テストを消せば問題解決です。CIダッシュボードも緑のチェックを表示します
    • 同意します
      LLMは今より絶対に良くならないし、過去2年間まったく進歩していません。単なる派手なマルコフ連鎖にすぎません
      コーディングを知らない人が、何のレビューもなしに本番へコードを盲目的にコミットするときにだけコード作成に使えます
      コーディングを知っている人に役立つはずがなく、生産性も高められません
      世界をまったく変えないこのLLMのでたらめは無視しますし、あなたも必ずそうすべきです
  • きちんと分離しておかないと、無知な管理者が高いカバレッジを要求し、熱心なジュニアが大量のAIテストをこっそり入れることで、簡単に開発者に敵対的な環境になってしまう。
    結局、作業を提出するたびに、保守しにくいLLM生成のテストコードからお墨付きをもらわなければならない状況になる。
    一部のテスト作成は速くなるかもしれないが、保守が速くなる保証はない。テスト対象コードの保守についても同じだ。良いテストが生成される保証がないからだ。
    テストを書く過程で苦労することは、開発者が設計を早い段階で点検するのにもたいてい役立つ。テストしにくいなら、たいてい良い設計ではなく、例えば他の人たちと一緒にコードを書く文脈では、コンポーネントの契約が十分に抽象化されていないことが多い。
    見落としがちなのは、テストは犠牲にできるコードだという点だ。大半は生涯何も検出しないだろうし、それでも問題ない。自動化された安心感を与え、失敗時には誤った手がかりを減らしてくれるからだ。
    しかし、確率的な安全装置に最大限投資しても、常に見返りがあるわけではない。カバレッジが上限に近づくほど限界効用は下がる。標準ライブラリのようにトラフィックの多い実行経路でない限り、高いカバレッジを誇ってもたいてい報われない。
    さらに、ほぼ常にユニットテストだけでなく、統合テスト、システムテストなどのテストエコシステムがあってこそ全体が回る。LLMは設計会議に座ってアーキテクチャを理解し、そうしたテストも書いてくれるのだろうか? それとも、できることが誇張されて、やるべきことを押しのけるのだろうか?
    テストに労力を投じるときは、作成時点だけでなく、設計や保守の時点でも「何が関係あるのか」を判断する感覚が必要だ。人間はこれをかなりうまくやるが、AIツールはそうではない。
    LLMが時間を節約してくれる部分は、何をテストすべきで何をテストしなくてよいかの勘をすでに持っている熟練開発者のキー入力だ。同時に、あまり関係のないものをコードにこっそり持ち込ませて邪魔になることもあり得るし、すでにそうなってきた。
    キー入力を生産する経済は望んでいない。十分に考えられた、関連性の高いキー入力の集合が欲しい。そして後者が前者とうまく分離され、時間が経つにつれて客観的な効用、あるいはその不在が明らかになることを望んでいる。

  • すでにGPT-4で試した。
    TypeScriptモジュールを見せてユニットテストを生成するよう頼んだところ、正常系だけでなく、いくつかの境界ケースまでカバーする、動作するテストを作ってくれた。

    • 似たようなコメントがなぜダウンボートされるのか、あまり共感できない。
      ChatGPTはいろいろな面で期待以上のことをしてくれる。テストはGPTの能力基準では簡単に見える。
      先週は、ASTを走査してReact Flowのグラフとコンポーネントを作るPythonコードを書かせた。修正はせず、プロンプトでのフィードバックを何度か繰り返したところ、とてもうまく動作した。GPTでは同様の興味深い能力をたくさん見てきた。
  • AIはどのテストを書くべきかをどうやって知るのか?
    興味深い実験ではあるが、やや疑わしい。ソフトウェア開発でAIが最もうまく支援できる方法は、プログラマーが自分のコードや他人のコードについて質問し、AIがそれに答えることだと思う。時にはコード提案が含まれるだろうが、常にそうである必要はない。
    「このコードを単純化する方法はあるか?」「どんな入力がエラーを引き起こし得るか?」といった質問に答えられるべきだ。
    AIは、私たちがコードを理解し、改善方法を理解するのを助けるべきだ。私たちが何をしてほしいかを言わなければ、AIは私たちの望みを知ることはできないので、すべてを自分で書かせるべきではない。
    テストは良い例だ。私たちは何をテストしたいのか?

  • ついに納得できるAIコード生成が出てきた