フロントエンドとバックエンドの変更を1つの自動化されたワークフローでテストする方法

Zeshi Du
フロントエンドとバックエンドの変更を1つの自動化されたワークフローでテストする方法 カバー

機能がフロントエンドだけ、またはバックエンドだけに完結することはほとんどありません。新しいチェックアウトフローは、UIフォームとその背後にある決済APIの両方に影響します。それら2つの部分を別々のツールで、別々のタイミングでテストすることが、UIテストが通り、APIテストも通り、それでも実際の統合が壊れている、という状況を生む原因です。ここでは、両方を単一のワークフローでテストする方法を紹介します。

分割テストが本当のバグを見逃す理由

典型的なパターンはこうです。フロントエンドのテストでチェックアウトフォームが正しく送信されることを確認し、APIテストで有効な入力に対して決済エンドポイントが正しいレスポンスを返すことを確認する。しかしどちらのテストも、フォームがAPIの期待するペイロードを送信しているかどうか、またはAPIのレスポンスがUIで正しく処理されているかどうかを実際には確認していません。このギャップ、つまりフロントエンドとバックエンド間の実際のコントラクトこそが、多くの本番バグが潜む場所です。そして、別々に実行・スコープされた2つのテストスイートには、このギャップが見えません。

フロントエンドとバックエンドのテストを完全に別々のワークフローとして実行することは、セットアップ・メンテナンス・結果の確認がそれぞれ別々になることも意味します。これにより、プロダクトの変更に合わせて両方を最新の状態に保つためのオーバーヘッドが増大します。

統一されたワークフローに実際に必要なもの

両方のレイヤーをカバーする単一の意図ソース。PRD(作成済みのものでも、コードベースから推論されたものでも)がチェックアウトフローの「買う」ボタンのクリックから注文確定までのエンドツーエンドの動作を説明していれば、同じソースから読み込むテストエージェントが、フロントエンドとバックエンドのカバレッジを生成できます。これは、バラバラな2つの部分ではなく、同じ機能を実際にテストするものになります。

同じトリガーから実行されるフロントエンドとバックエンドのテスト生成。UIテストスイートとAPIテストスイートを別々のコマンドや別々のCIジョブとして起動するのではなく、単一の指示で両方を生成・実行できるべきです。これにより、同期を保つ必要がある2つのパイプラインを手動で調整する手間がなくなります。

バックエンドのアサーションを実際の観察結果に基づかせること。フロントエンドのテストは、実際のユーザーが見るものを確認することで効果を発揮します。バックエンドのテストは、アサーションを生成する前に、APIが実際に返すもの、つまり実際のステータスコード、実際のフィールド名、実際のレスポンス形式を確認することで効果を発揮します。フロントエンドコードのバックエンドに対する仮定ではなく、実際に観察された動作にバックエンドのアサーションを基づかせることが、UIが期待するものとAPIが実際に返すものとのミスマッチを検出するカギです。

実践的なワークフロー

1. エージェントを動作中のアプリケーション(フロントエンドとそれが呼び出すAPI)に向ける。IDEでの単一の指示であれ、ダッシュボードのプロジェクト設定であれ、セットアップ手順はスタックの両方を認識できるものであるべきで、それぞれに別途設定を必要とするべきではありません。

2. 同じ意図から両方の側面のテストを生成させる。チェックアウト機能であれば、フォームの操作とエラー状態をカバーするUIテストケースと、決済エンドポイントのコントラクトをカバーするバックエンドテストケースを、互いを参照しない2つの独立したプロセスではなく、まとめて生成します。

3. バックエンド層に実際のAPI動作を観察させてからアサーションを生成させる。これがフロントエンド・バックエンド間のコントラクトのミスマッチを実際に検出するステップです。チェックアウトエンドポイントが返すものを仮定するのではなく、テストエージェントがまず実際のレスポンス形式を観察し、その観察結果に基づいてアサーションを生成します。これにより、フロントエンドのAPIに対する仮定が実際と一致しない場合が自然に浮かび上がります。

4. 両方のレイヤーを実行し、別々のダッシュボードではなく、一緒に結果を確認する。同じ機能のフロントエンドとバックエンドのテスト結果を並べて表示する単一のレポートがあれば、一方のレイヤーは通過したが他方は通過しなかったという場合にすぐ気付けます。これはしばしば、レイヤー間のコントラクトがズレているという正確なシグナルです。

5. 動的な変数を使って、マルチステップフロー全体で2つのレイヤーを接続する。実際のチェックアウトフローでは、フロー前半で作成されたカートIDやセッショントークンを後のステップに引き継ぐ必要があります。フロントエンドのインタラクションとそれが引き起こすバックエンドの呼び出しの両方でこれが必要です。これらの値を両方のレイヤーにわたって自動的にキャプチャ・受け渡しするワークフローにより、クロスレイヤーテストをもろくしがちな手動の配線が不要になります。

具体的な例

例えば、アプリのサインアップフローにフロントエンドフォームと、アカウントを作成してセッショントークンを返すバックエンドエンドポイントがあるとします。統一されたテストでは次のことを行います。実際のユーザーと同様にフォームに入力し、バックエンドが実際に返すトークンをキャプチャし、そのキャプチャしたトークンを使って続く認証済みリクエストが正しく機能することを確認し、その後UIがログイン状態を正しく反映しているかを確認します。フォームとエンドポイントを別々にテストすると、それぞれ単独では問題ないように見えますが、バックエンドが実際に返すトークンをフロントエンドが正しく保存・使用しているかどうかは確認できません。

AIが生成した機能で特にこれが重要な理由

AIコーディングエージェントが同じパスでフロントエンドフォームとバックエンドエンドポイントの両方を書いた場合、別々に実行されるテストでは検出できない特定のリスクがあります。エージェントが持つ2つの部分間の内部的な一貫性が、両方で同時に誤った仮定に基づいている可能性があるからです。例えばエージェントが、リクエストペイロードとレスポンスの両方でフィールド名を`userId`と仮定していたとして、その仮定が実際のデータベーススキーマに対して単純に誤っていた場合、フォームの動作を確認するUIテストとエンドポイントのレスポンスを確認するAPIテストは、それぞれの内部ロジックの観点からは通過できます。しかし実際の統合はサイレントに失敗します。実際のリクエストと実際のレスポンスを一緒に観察する統合テストだけが、両方のレイヤーにわたって一貫して誤っている仮定を検出できます。なぜなら、各側面の内部ロジックだけでなく、実際のレイヤー間の接続を確認しているからです。これが、別々に実行されるテストが構造的に見えないことのある、特定の失敗モードです。それぞれがどれほど徹底していても同様です。

まとめ

フロントエンドとバックエンドの変更が互いに独立して起こることはほとんどなく、それらを独立してテストすることは、統合バグが潜む正確なギャップを残します。単一の意図ソースによって駆動され、実際に観察されたバックエンドの動作に基づく統合ワークフローは、別々のテストスイートが構造的に確認できない2つのレイヤー間のコントラクトを検出します。これは「両方の部分が個別に通過する」とは意味が異なり、機能が実際のユーザーに届く段階で本当に重要な保証です。TestSpriteは、同じPRDから、1つのワークフローで、ツールを切り替えることなく、フロントエンドとバックエンドの両方のカバレッジを生成します。