Playwrightのバグ調査は書いて捨てる|「このバグ直して」が指示書に変わる

ども!バグ調査のたびにPlaywrightを使い捨てして快適なバグ修正を行っている龍ちゃんです。

バグが来たら、AIに一旦調査させてみる。んで見立てを立てるじゃないですか。

その見立て、合ってましたか。

これがけっこう外してました。読んで「いいんじゃない?」と思って許可して、通ったから終わりにして、しばらくして治っていない。結局コードを読む。

痛いのは「自分でコードを読む」ことじゃないんですよね。ドキュメントレベルをさらっと読んでも確定しないことです。

なので提案はこれです。Playwrightを使い捨てで書いて、バグ調査に使う。 恒久的な回帰テストとして残すためではなく、原因を確定させるために書いて、終わったら捨てる。

今回の内容です。

  • 画面に出るバグを、使い捨ての再現で詰める6工程
  • 再現を書かせるのは、実装したセッションの外がいいという話
  • 再現条件が確定すると「このバグ直して」が別物になる、という話
  • 一番の強敵は flaky で、そこをどう手当てしているか

想定しているのは、Playwrightで E2E を書いて、CIに乗せて回している人です。扱うのは画面に出るバグだけに絞ります。表示が崩れる、押せない、閉じない、みたいな種類ですね。ロジック層やバッチみたいに画面に出ないものは、この手順そのものが当てられません。

先に予防線を張っておきます。これはコードを読まなくて済む話ではありません。読む位置が変わる話です。 AIに丸投げする方向とは、むしろ逆を向いています。

画面に出るバグは、この6工程で回してます

前提を揃えます。Playwrightはもう入っていて、E2Eを書いてCIで回している。その状態にバグが1件飛んでくる、というところからの話です。

飛んでくるのは、表示が崩れている、ボタンが押せない、ダイアログが閉じない、みたいなやつですね。画面を見れば起きていることは分かる。でも、なぜそうなるかは分からない。 そこからどう詰めるかを書きます。

全体感としてはこんな感じです。

  1. 使用感で気づく
  2. AIと議論して、原因を特定して言語化する
  3. 画面に出るものなら、再現を書かせる
  4. まず落ちることを確認する
  5. 修正して、つぶれたことを再現で確認する
  6. 済んだら捨てる

要所で人間がスクショを見ます。順に見ていきますね。

画面に出るバグを使い捨ての再現で詰める6工程を、人のレーンとAIのレーンに縦に分けて手描き風に描いたスイムレーン図。縦に降りるほど工程が進み、左右のどちらに箱があるかが担当を表す。①使用感で気づくのは人で、Issue でもレビュー指摘でもよい。②議論して原因を言語化するのは人とAIの両方にまたがる作業で、実装させない・人間向けに丸めさせない・推測を事実として書かせないの3つで縛る。③実装した文脈から切るのは人が決める。別のセッションだと容赦なく指摘してくるため。再現を書くのはAIで、画面に出る症状に限る。④落ちた事実で資料を確定させるのは人で、ここが関門。修正する前に、ちゃんと落ちるのを見る。越える前に落ちるのを見ないと、あとで通ったときにバグが直ったのかテストが空振りしたのか区別がつかない。⑤新しいセッションで直すのはAIで、資料だけ渡してまず疑わせ、落ちていたものが通る。同時に人がスクショを見る。文言の位置はアサーションに書けないためで、表示位置が違って差し戻したこともある。⑥捨てるのは人で、残すのはスクショだけ。出口では再現条件が確定する。渡すのは条件で、再現コードではない。レーンをまたぐ線が4本あり、AIに書かせて人が見てまた返す行き来がそのまま工程になっている

① 入口は問わない

Issueでもレビュー指摘でも、自分で触っていて気づいたのでもいい。ここは通過します。その見立てが合っているかを確かめるのが、ここからです。

② 調査結果を1枚にまとめさせて、3つだけ縛る

ここでやるのは、原因の見立てをAIと一緒に言葉にすることです。この型そのものは前に書いたので、詰め方はドキュメント1枚を先に書く話と同じです。

まとめさせるときに縛るのは3つです。

  • 実装させない(対策は方針まで)
  • 人間向けに丸めさせない
  • 推測を事実として書かせない

ここを縛らないと、読みやすい嘘が出てきます。読みやすいので気づきにくいんですよね。

そして、この工程でいちばん危ないのは、出てきた結果を確かめずに修正に入ることです。調査結果って、もっともらしく納得できる形で出てくるんですよね。読んだ時点で正解に見える。でも読んで納得したことと、実際にそう動くことは別です。確かめるのは④でやります。

③ 実装の外で、画面に出る症状だけを書かせる

条件が2つあります。どっちを外しても、書いた再現が証拠になりません。

使い捨ての再現を投げていい症状の線を、横軸に症状が画面に出るかどうか、縦軸に誰が担当するかを取って手描き風に描いた2軸マップ。画面に出る症状をPlaywrightに任せる象限には、表示が崩れる・押せない・閉じないが入り、ここは使い捨ての再現で詰められる。画面に出ないものをPlaywrightに任せる象限は点線で、モックして数えるのはできるが、数えているのは自分が用意した通信であって実環境で起きていることの捕捉ではないため、得意じゃない領域。画面に出るものを人が担当する象限はスクショを見て判断すること。文言の位置はアサーションに書けないため。画面に出ないものを人が担当する象限はHARを取ってくること。実環境で何が飛んでいるかは人の仕事。そもそも画面に出ないもの、ロジック層やバッチなどには、この手順そのものが当てられない

ひとつは、症状が画面に出るものに限ること。Playwrightが得意なのはそこです。ネットワークの中身、つまり実環境で実際に何が飛んでいるかを捕まえるのは得意な領域じゃないので、そこは人間がHARを取ってくる側の仕事になります。さきほど挙げたドキュメント1枚の話が、その側ですね。

もうひとつは、再現を書かせる文脈を、実装した文脈から切ること。

実装したセッションにそのまま再現を書かせると、自分が脆いと知っている経路を無意識に避けるんですよね。同じ文脈が持っている前提を、そのまま持ち込むので。別のセッションを立てると容赦なく指摘してくるし、めちゃくちゃなテストをしてくれる。人に頼むのと同じですね。分けたほうが証拠として強くなります。

どの粒度で分けるかはセッションを分ける運用の話で書いたので、ここでは再現を書かせるぶんだけにします。

同じ問題は社内でも書かれていて、AIにテストを書かせると実装をコピーしたテストになるという話です。あちらは同じAIの中で読む権限を剥がして解決していました。こっちはセッションを分けて、間に人が資料を通しています。見ている壊れ方は同じで、解決の主語が違うだけです。

④ 落ちるのを見て、調査資料を確定させる

ここが、この手順でいちばん大事です。

修正する前に、書いた再現がちゃんと落ちることを確認する。飛ばすと、あとで通ったときにバグが直ったせいなのかテストが空振りしているせいなのか区別がつきません。

もっとも、落とせないやつもあります。表示が崩れている、文言の位置がおかしい、みたいなアサーションに書けない種類ですね。そこは落ちなくていいので、修正前の症状が写ったスクショを撮ります。落ちる代わりに、それを証拠にする。やっていることは同じで、修正する前の状態を固定しているだけなので。

ただ、動かして見せるだけならただの動作確認なんですよね。大事なのは、落ちたという事実で②の資料を書き換えることです。仮説として書いてあった原因が、動作で確定した事実になる。ここで初めて、実装に投げられる資料になります。資料に何をどう書くかは、それ自体で1本になるのでここでは扱いません。

一度、修正案を5つ作って全部動かしたことがあります。理屈でいちばん正しそうに見えた案が、動かすと効かなかったんですよね。読んで考えた結論って、けっこう外れます。だから動作のほうから確定させます。

あわせて、ここで決めておくことがあります。直す範囲をどこまで広げるかです。

こういうことがありました。押せないというバグが上がってきて、報告にあったのは1画面だけ。でも調べたら原因は共通の部品側で、その部品を使っている画面が全部同じバグを持っていました。直す範囲は5箇所になります。いわゆる横展開ですね。しかも、報告に無かった箇所がいちばんひどかったんですよね。「あっちは行が高いから当たりにくいだろう」と踏んでいたのが、動かしたら外れていました。

逆に、その画面だけ直せば済むバグもあります。あったりなかったりなので、影響範囲を確認して決めるしかない。決めずに実装へ投げると、そこをAIが補完してしまいます。

⑤ 資料を新しいセッションに渡して、まず疑わせる

ここでもう一回、答え合わせをします。修正は新しいセッションでやって、持たせるのは資料だけ。実装の文脈は引き継がせない。③と同じ切り方ですね。

そのとき、いきなり直させないんですよね。「資料はこう言ってるけど、どうなんかな?」と一度聞いてから実装に入らせます。確定しているといっても、確定させたのは自分なので。ここでもう一回、答え合わせをしている感じです。

あとは楽で、落ちるところまで作ってあるので、通るのを見るだけです。

あわせて、要所でスクショを撮って人間が見ます。文言の位置がおかしいみたいなのはアサーションに書けないので。実際、エラーの表示位置が想定と違っていて差し戻したことがありました。

⑥ 元を取ろうとせず、捨てる

やることは短くて、設定ファイルに使い捨て用の項目を数行足して、書いて、回して、消す。それだけです。

「せっかく書いたのに」と思いますか。でもPlaywrightを手で書くの、大変じゃないですか。恒久化してCIに乗せろというのは、書くのが高かった時代の合理なんですよね。安く書けるなら、無理に元を取る必要がない。必要ならまた作ればよいんです。

残すのは基本スクショだけです。逆に、UIのデグレチェックは全部撮って残すべきだと思っています。あれは原因の言語化が要らなくて、人間が見て判断するものなので、性質がまったく違う。

もちろん、E2Eとして残す価値があるものはそのつど出てきます。全部捨てろという話ではないんですよね。ただ、その線引きは僕もまだ言葉にできていません。

たまに、E2Eとして新設するところまでをタスクとして切ることもあります。要は効果があるかないかって都度判断ですね。

この手順を踏むと「このバグ直して」が指示書に変わる

何が変わるか。再現条件が確定します

どう操作したら、どういう状態で、何が起きるか。そこに、どこまで直すかまで乗っています。そこまで固まると、コードのどこが問題かも自然に絞れています。

その状態で出す「このバグ直して」は、もう別物なんですよね。角度の高い指示書になっている。同じ一言なのに、返ってくるものが変わります。

ひとつだけ注意があって、ここで渡しているのは再現コードじゃありません。

テストコードを渡して「これを通るように直して」とやると、テストを通すためのコードが返ってきます。渡すのは、再現で確定した条件のほうです。

Playwrightで一番の強敵はflakyでした

再現を作るとき、いちばんの敵はflakyな挙動でした。

再現しようとすると別のバグっぽい挙動が出て、よく見たら読み込み待ちだった、みたいなことが起きるんですよね。

困るのは「テストが不安定でつらい」からじゃないんです。落ちたのがバグなのか環境なのか区別がつかないと、答え合わせにならないからです。確定させるために書いているのに、確定しない。ここが崩れると工程ごと意味を失います。

flakyそのものを避ける仕組みはPlaywrightの中に入っていて、正直そこは僕は説明できません。意識しないうちに助けられていたので。詳細は公式の Auto-waiting のページに譲ります。

自分でやったのは1つだけで、踏んだ穴をそのつどAIに記録させることです。この型は踏んだ失敗を溜めて指示ファイルを育てる話で書いたので、ここではPlaywrightに当てたぶんだけです。

手元にその記録が溜まっていて、撮影まわりだけで5,375行あります。全部、一度踏んだ穴です。「3件通ったように見えて、実は1件も走っていなかった」みたいなのも入っています。

記録させてあるので、似た穴は二度目がない。だから超絶快適なんですよね。ここが「使い捨てで回すとはかどる」の実体だと思っています。

変わったのは、読む位置でした

正直に書いておくと、この運用も無傷じゃありません。

当てられないバグに当てて、失敗したこともあります。画面に出ないやつですね。導入で範囲を切ったのは、実際にそこで転んだからです。逆に、フロントの表示系ならだいたいこれで潰せています。測ったわけではなくて、実感ですけど。

一度、撮ったスクショが消えていて、記録から書き戻して撮り直したら構文エラーで動きませんでした。貼った時点で壊れていても気づけないんですよね。捨てる運用は、捨てたものが確実に戻る保証まではくれません。

それでも、変わったのは順番でした。

コードを読んで考えて見立てを立てるところから、動かして確定させてから読むところへ。読む位置が移ったんです。指示書の精度は、全部そこから出ています。

読むのは最終手段です。 ただ、読む前に何が起きているかは確定している。最初に張った予防線はそういう意味でした。

答え合わせの道具そのものが壊れていた話もあるんですが、それは別記事で書きます。再現があってもAIに任せきれない理由、こっちはリポジトリ側の事情なんですが、それも別に置くつもりです。

最後に、最初の一歩を1つだけ。

次のバグで、修正する前に「落ちる再現」を1本書いてください。 それだけで、直したあとに自分が何を確認したのかが変わります。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。
エンジニア募集中!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です