はじめに
AIにUIの修正を依頼すると、実装だけでなくブラウザを操作して動作確認まで行わせることができます。
ただ、毎回AIに「画面を開いて確認して」と依頼するだけでは、その場では確認できても、次の修正で同じ不具合が再発したときに自動で検知できません。
そこで、再発しやすいUIの振る舞いについては、手動の動作確認だけで終わらせず、PlaywrightなどのE2Eテストとしてコードに残す方が有効です。
この記事では、AIにUI修正を任せる場合に、
- 手動動作確認とE2Eテストをどう使い分けるか
- どのようなUIをE2Eテストにするべきか
- E2Eテストをどのタイミングで実行するか
- 修正とテストをどのようにコミットするか
を整理します。
手動動作確認だけでは回帰テストにならない
例えばAIに次のように依頼したとします。
この画面の入力処理を修正してください。
修正後、ブラウザで実際に操作して問題ないことも確認してください。
AIがブラウザを操作して正常に動くことを確認できれば、その修正に対する動作確認としては有効です。
しかし、確認結果そのものはコードとして残りません。
UI修正
↓
AIがブラウザ操作
↓
正常だった
↓
後日別の修正
↓
同じ箇所が壊れても自動では分からない
一方、E2Eテストを追加しておけば、後続の変更でも同じ操作を繰り返し確認できます。
そのため、バグ修正や仕様として重要なUI操作は、可能であればE2Eテストとして残した方がよいです。
E2Eテストを書く価値が高いUI
すべてのUI修正をE2Eテストにする必要はありません。
例えば、次のような振る舞いはE2Eテストと相性がよいです。
- 画面遷移
- フォーム入力
- フォーカス移動
- モーダルの開閉
- ボタンの活性・非活性
- APIレスポンスに応じた表示切り替え
- 入力エラーの表示
- 過去に不具合が発生した操作
逆に、余白を少し変更した、色を変えた、文言を変更した、といった修正まで毎回E2Eテストにすると、テストコードの保守コストが大きくなります。
見た目ではなく、ユーザー操作として壊れると困る振る舞いをE2Eテストにします。
年月日を別々の入力欄にするUI
例えば、生年月日を次のようなUIで入力するとします。
[ 西暦 | 昭和 | 平成 | 令和 ]
年 [ ] 月 [ ] 日 [ ]
仕様として、次のような動作があるとします。
- 西暦を選択した場合、年は4桁入力する
- 年を4桁入力したら、自動的に月入力欄へフォーカスする
- 月を2桁入力したら、日入力欄へ移動する
- 昭和・平成・令和では元号に応じた年のバリデーションを行う
- 不正な日付の場合はエラーを表示する
このようなUIはE2Eテストを書く価値が高いです。
単なる値の検証だけではなく、実際のキー入力、フォーカス、元号切り替え、エラー表示が組み合わさったUI仕様だからです。
4桁入力後のフォーカス移動もE2Eでテストできる
Playwrightでは、入力後にどの要素へフォーカスが移動したかも確認できます。
例えば次のように書けます。
const year = page.getByLabel('年')
const month = page.getByLabel('月')
await year.click()
await year.pressSequentially('2026')
await expect(month).toBeFocused()
ここでは fill() ではなく pressSequentially() を使っています。
フォーカス移動がinputイベントやキー入力のたびに文字数を確認して実行される実装なら、実際のユーザー入力に近い方法でテストする方が安全です。
さらに、3桁の時点では移動せず、4桁目を入力した瞬間に移動するところまで確認できます。
await year.click()
await year.pressSequentially('202')
await expect(year).toBeFocused()
await year.press('6')
await expect(month).toBeFocused()
これにより、単に最終状態を見るだけではなく、UIの途中の振る舞いも回帰テストとして残せます。
バリデーションロジックは全部E2Eにしなくてもよい
例えば次のような判定があります。
- 13月は不正
- 32日は不正
- うるう年を考慮する
- 元号の範囲外は不正
これらをすべてE2Eだけでテストすると、ブラウザを起動するテストが大量に増えます。
日付計算や元号変換などを純粋な関数へ切り出せるのであれば、ロジック自体はユニットテストで確認した方が高速です。
例えば、次のように責務を分けられます。
ユニットテスト
├─ 日付の妥当性
├─ うるう年
├─ 元号の範囲
└─ 西暦・和暦変換
E2Eテスト
├─ 実際に文字を入力できる
├─ 4桁入力後にフォーカスが移動する
├─ 元号を切り替えられる
├─ エラーが画面に表示される
└─ 正しい値で送信できる
E2Eでは「ブラウザ上で正しく連携しているか」を確認し、計算ロジックの細かいパターンはユニットテストへ寄せるとバランスがよくなります。
E2Eテストは修正のたびにフル実行しない
E2Eテストはユニットテストと比べると実行コストが高くなります。
そのため、1行修正するたびにE2Eテスト全体を実行する必要はありません。
開発中は、変更した機能に対応するテストだけを実行します。
UIを修正
↓
関連するユニットテストを実行
↓
対象のE2Eだけ実行
↓
追加修正
ある程度修正がまとまったら、関連するE2Eをまとめて実行します。
最後にPRを作成する前やCI上でフルE2Eを実行します。
開発中
対象E2Eだけ実行
一区切り
関連E2Eをまとめて実行
PR前・CI
必要に応じてフルE2E
この運用なら、E2Eの安心感を得つつ、開発中の待ち時間を抑えられます。
AIには修正だけでなく回帰テストまで依頼する
AIにUI修正を依頼するときは、単に
この不具合を修正してください。
とするより、次のように依頼すると回帰テストまで残せます。
このUIの不具合を修正してください。
修正後はPlaywrightで対象操作のE2Eテストを追加してください。
特に次を確認してください。
- 年を3桁入力した時点では年入力欄にフォーカスが残る
- 4桁目を入力したら月入力欄へフォーカスが移動する
- 不正な日付ではエラーが表示される
開発中は対象テストだけ実行し、最後に関連するE2Eテストをまとめて実行してください。
AIはテストコードを書く作業とも相性がよいため、人間が毎回手で行っていた確認手順を、そのまま回帰テストとしてコード化しやすくなります。
修正コミットとE2Eテストコミットを分ける
修正とテストは論理的に分けておくとレビューしやすくなります。
例えば次のようにします。
fix: 生年月日入力時のフォーカス移動を修正
test: 生年月日入力のE2Eテストを追加
こうしておけば、
- 何を修正したのか
- その修正をどのテストで保証しているのか
を分けて確認できます。
ただし、AIがブラウザを操作して確認しただけでファイル変更がない場合は、動作確認専用のコミットを作る必要はありません。
その場合はPRの説明に確認結果を残せば十分です。
## 動作確認
- 西暦を選択
- 年を4桁入力すると月へフォーカスが移動することを確認
- 不正な日付でバリデーションエラーが表示されることを確認
おすすめの流れ
AIを使ってUIを修正する場合、次の流れが扱いやすいと考えています。
AIによる手動動作確認をE2Eテストの代わりにするのではなく、重要な確認手順をE2Eコードへ昇格させることがポイントです。
まとめ
AIにUI修正を任せる場合、ブラウザでの手動動作確認だけでもその場の確認には役立ちます。
ただし、画面遷移、フォーカス移動、入力制御、バリデーションなど、後から壊れる可能性のあるUI仕様はE2Eテストとして残した方が安全です。
特に、年月日の入力欄で「年を4桁入力したら月へ自動フォーカスする」といった挙動は、Playwrightで実際のキー入力とフォーカスをそのままテストできます。
運用としては、
- ロジックはユニットテスト
- ブラウザ上のユーザー操作はE2E
- 開発中は対象E2Eだけ実行
- 修正がまとまったら関連E2Eを実行
- PR前やCIで必要に応じてフルE2E
と分けると、テスト時間と安心感のバランスを取りやすくなります。
AIに実装だけでなくE2Eテストコードまで書かせることで、これまで人間が繰り返していた手動動作確認を、継続的に実行できる回帰テストへ変えていけます。