Playwrightのテストは合格します。ログインボタンがクリックされ、ダッシュボードがレンダリングされ、チャートが描画されます。しかし、顧客からバグが報告されます。チャートの数値が間違っているというのです。調査すると、APIが200ステータスを返しているものの、ペイロードが不正であることが判明します。そして、エンドツーエンドのスイートは、画面にピクセルが表示されることしか確認していなかったため、これに気づきませんでした。ブラウザテストだけでは埋められないこのギャップこそ、APIアサーションが不可欠となる部分です。Apidogのようなツールは、UIフローに適用するのと同じ厳格さでAPIコントラクト、スキーマ、レスポンスのセマンティクスを検証する方法を提供し、その後、両方のスイートをCIで同時に実行できます。
ボタン
要約
Playwrightのrequestフィクスチャとpage.routeインターセプターを、同じOpenAPI仕様にヒットするApidogシナリオと組み合わせることで、Playwrightテスト内でAPIを検証できます。単一の仕様ファイルを介してフィクスチャを共有し、両方のレイヤーでレスポンススキーマをアサートし、1つのCIジョブで両方のスイートを実行することで、コントラクトの変更がどちらかの場所で迅速に失敗するようにします。
はじめに
Playwrightは、2026年には多くのチームにとってデフォルトのブラウザ自動化フレームワークとなっており、PlaywrightのドキュメントではAPIテストが簡単に見えます。数回のrequest.get呼び出し、1つのexpect(response.status()).toBe(200)で完了です。問題は、それをスケールアップするときに始まります。ステータスコードはチェックするがレスポンスの形状はチェックしない何百ものテスト、ブラウザフローとAPIフローの間で共有される唯一の信頼できる情報源がない状態、そしてバックエンドが遅いか壊れているときにAPIをオフラインでモックする方法がない状態になってしまいます。
解決策は単純です。OpenAPI仕様を契約として扱い、その契約に基づいてPlaywrightのrequest呼び出しとpage.routeインターセプターを駆動し、同じ仕様に対してApidogシナリオスイートを実行して、深いスキーマ、ビジネスロジック、および連鎖リクエストの検証を行います。これにより、CIでの迅速なフィードバック、フロントエンドとバックエンドテスト間の明確な所有権の境界、そして重複したフィクスチャがなくなります。まずツールをインストールしたい場合は、Apidogをダウンロードして戻ってきてください。以下の手順は、それがローカルで利用可能であることを前提としています。
この投稿から得られるものは次のとおりです。PlaywrightスイートでAPIアサーションがどこに属するかのクリーンな精神モデル、機能するrequest.fixtureパターン、PlaywrightとApidog間でフィクスチャを共有するためのステップバイステップのセットアップ、CIとモックに関する高度なヒント、そして主要な代替ツールの比較表です。テストツールの選択に関するより広範なコンテキストについては、QAエンジニア向けのAPIテストツールに関する私たちの見解をご覧ください。
PlaywrightテストとAPIアサーションの間のギャップ
典型的なPlaywrightテストは、ログインし、ページに移動し、いくつかのUI要素が表示されていることをアサートします。これは、ユーザーに見えるフローが機能していることを示しますが、その背後にあるAPIについては何も教えてくれません。次の3つの障害モードが見過ごされてしまいます。
まず、ペイロード形状の退行です。エンドポイントは200を返しますが、フィールド名がtotal_countからtotalCountに変更されています。UIはサイレントに型変換するか、ゼロを表示するかもしれません。Playwrightテストは画面上の数値を見て合格とします。
次に、ビジネスロジックのずれです。割引エンドポイントが、契約上の15%ではなく10%のリベートを適用します。UIはAPIが返すものを表示するため、テストは合格します。数週間後になって、財務チームだけが気づきます。
3番目に、エラーパスの網羅性です。Playwrightテストはほとんどの場合、ハッピーパスを実行します。APIには、レート制限、期限切れトークン、部分的な失敗、べき等性競合など、数十の4xxおよび5xxブランチがあります。個別のAPIテストスイートを作成しない限り、これらはどれも実行されません。
Playwrightの仕様内にrequest.get呼び出しを追加し、レスポンスボディをアサートすることで、この一部をパッチ適用できます。これは少数のエンドポイントでは機能します。しかし、200のエンドポイントがあり、「注文を作成し、注文を取得し、注文をキャンセルし、払い戻しwebhookを検証する」といった連鎖的なシナリオを求められると、破綻します。Playwrightはまずブラウザ自動化フレームワークであり、ステートフルなAPIワークフローやスキーマレベルのアサーションの人間工学のために構築されていません。それが、専用のAPIテストツールがその価値を発揮する場所です。
適切な分割は次のとおりです。
- Playwrightテストは、UIフロー、ネットワークインターセプション、およびユーザーアクションの境界での薄いAPIスモークチェックを検証します。
- Apidogシナリオは、スキーマの準拠、連鎖したAPIワークフロー、コントラクトの遵守、およびエラーパスを詳細に検証します。
両方のスイートは同じOpenAPI仕様を消費するため、2つのバージョンの真実を持つことはありません。契約優先アプローチに関するより深い見解については、設計優先APIワークフローに関する私たちの記事が、周辺パターンを説明しています。
PlaywrightとApidog間でフィクスチャを共有する方法
唯一の信頼できる情報源は、通常リポジトリのルートにあるopenapi.yamlまたはopenapi.jsonです。Playwrightは型付けされたリクエストヘルパーと例のペイロードのためにこれを読み込み、Apidogはシナリオステップを埋めるために直接インポートします。バックエンドが契約変更を出荷するたびに、両方のスイートがそれを取得します。
再利用可能なテストデータ(ユーザー、トークン、サンプルペイロード)を保持するfixtures/フォルダーから始めます。これらをロードし、テストに公開するPlaywrightフィクスチャファイルを作成します。
// tests/fixtures/api.ts
import { test as base, APIRequestContext, expect } from '@playwright/test';
import { readFileSync } from 'fs';
import path from 'path';
type ApiFixtures = {
apiRequest: APIRequestContext;
authToken: string;
sampleOrder: Record<string, unknown>;
};
export const test = base.extend<ApiFixtures>({
apiRequest: async ({ playwright }, use) => {
const ctx = await playwright.request.newContext({
baseURL: process.env.API_BASE_URL ?? 'https://api.staging.example.com',
extraHTTPHeaders: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
});
await use(ctx);
await ctx.dispose();
},
authToken: async ({ apiRequest }, use) => {
const res = await apiRequest.post('/auth/token', {
data: { email: 'qa@example.com', password: process.env.QA_PASSWORD },
});
expect(res.status()).toBe(200);
const body = await res.json();
await use(body.access_token);
},
sampleOrder: async ({}, use) => {
const raw = readFileSync(
path.join(__dirname, '..', '..', 'fixtures', 'order.json'),
'utf8',
);
await use(JSON.parse(raw));
},
});
export { expect };
これで、各仕様で@playwright/testの代わりにこのフィクスチャファイルからtestをインポートするだけで、型付きのapiRequest、新しいauthToken、およびsampleOrderデータがすぐに利用できるようになります。order.jsonファイルは、ApidogがシナリオでPOST /ordersの例のボディとして使用するのと同じペイロードです。一度編集すれば、両方のスイートに変更が反映されます。
Apidog側では、プロジェクトを開き、「インポート」をクリックして、同じopenapi.yamlを指定します。Apidogはエンドポイント、リクエストの例、およびパラメーターのスキーマを数秒で生成します。その後、フィクスチャのペイロードをApidogの「環境変数」または「データセット」として保存します。
// tests/orders.spec.ts
import { test, expect } from './fixtures/api';
test('POST /orders returns a valid order with 15 percent discount', async ({
apiRequest,
authToken,
sampleOrder,
}) => {
const res = await apiRequest.post('/orders', {
headers: { Authorization: `Bearer ${authToken}` },
data: { ...sampleOrder, coupon: 'SAVE15' },
});
expect(res.status()).toBe(201);
const body = await res.json();
expect(body).toMatchObject({
id: expect.any(String),
status: 'pending',
discount_pct: 15,
total_cents: expect.any(Number),
});
expect(body.total_cents).toBeLessThan(sampleOrder.subtotal_cents);
});
Apidog内では、一致するシナリオステップが同じペイロードを投稿し、その後、openapi.yaml内のOrderコンポーネントに対して組み込みのJSONスキーマチェックを実行します。これにより、すべてのフィールドが型チェックされ、必須フィールドが検証され、列挙型値が強制されるという深い検証が可能になります。Playwrightは高価値のセマンティックアサーション(discount_pct: 15)をキャッチし、Apidogは手動でアサートすることを忘れたものも含め、逸脱するすべてのフィールドをキャッチします。仕様駆動テストに慣れていない場合は、設計優先APIワークフローに関する私たちの解説が、周辺パターンを示しています。
Postmanを既に利用しており、切り替えを検討しているチーム向けに、セルフホスト型Postman代替が移行メカニズムを解説しています。
Apidog + Playwrightワークフローのセットアップ
これは、約1時間でゼロからデュアルスイートCIを構築できる、クリーンで再現可能なセットアップです。
ステップ1:全てを統べる一つの仕様。 リポジトリのルートにopenapi.yamlを配置します。これをコードとして扱い、PRレビューを必須とし、破壊的変更にはメジャーバージョンアップを要求します。まだ持っていない場合は、既存のルートからフレームワークプラグイン(FastAPI、NestJSなどがネイティブでOpenAPIを出力)を使用してドラフトを生成し、手動で編集します。Apidogは、HARファイルをインポートすれば、トラフィックから仕様をリバースエンジニアリングすることもできます。
ステップ2:Playwrightを構成。 Playwrightをインストールし(npm init playwright@latest)、上記のフィクスチャファイルを追加します。npm run test:e2eスクリプトと、ステージング環境を指すplaywright.config.tsを追加します。テストは小さく保ち、1つの仕様につき1つのシナリオとします。
ステップ3:Apidogシナリオレイヤーを追加。 Apidogプロジェクト内でopenapi.yamlをインポートし、その後、サインアップ、チェックアウト、払い戻し、Webhook配信など、重要なユーザー体験ごとにシナリオを構築します。各シナリオは、アサーションが連鎖したAPI呼び出しのシーケンスです。Apidogは環境変数、リクエスト前スクリプト、レスポンス後アサーションをサポートしています。シナリオをApidog CLI(apidog-cli run scenario.json)を介してCLIで実行可能なJSONとしてエクスポートします。
ステップ4:Playwrightでのネットワークインターセプション。 UIがライブでヒットしたくないデータを取得する場合、page.routeを使用してインターセプトし、スタブを作成します。スタブされたレスポンスは同じフィクスチャファイルから来るため、契約は一貫して保たれます。
test('dashboard renders cached order list when offline', async ({
page,
sampleOrder,
}) => {
await page.route('**/api/orders', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ orders: [sampleOrder] }),
});
});
await page.goto('/dashboard');
await expect(page.getByTestId('order-row')).toHaveCount(1);
});
次にApidogでは、同じGET /ordersシナリオを実際のバックエンドまたはApidogモックサーバーに対して実行します。同じフィクスチャで、2つの検証層があります。
ステップ5:CI統合。 両方のスイートを並行して実行するGitHub Actionsワークフローを追加します。
name: tests
on: [push, pull_request]
jobs:
playwright:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20' }
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
apidog:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20' }
- run: npm i -g apidog-cli
- run: apidog-cli run ./apidog/scenarios/checkout.json --reporters cli,junit
どちらかのジョブが失敗するとマージがブロックされます。--reporters junitを使用して、GitHubがPR上で失敗したアサーションをインラインで注釈付けするようにします。GitHub Actionsのドキュメントには、これをスケールアウトしたい場合のマトリックスビルドとキャッシングが記載されています。専任のQA機能がないチーム向けには、QAエンジニア向けのAPIテストツールの解説が、各スイートの所有権を割り当てる方法を説明しています。
ステップ6:ドリフト検出。 テストが最後に実行されたバージョンと比較して、ライブのopenapi.yamlの差分を毎日実行するジョブをスケジュールします。フィールドの型が変更された場合、テストが実行される前に差分がビルドを失敗させます。これにより、冒頭で述べた「200 OKだがペイロードが間違っている」という種類のバグを捕捉します。
高度なテクニックとプロのヒント
基本的な設定が稼働した後で効果を発揮するいくつかのヒントです。
Playwrightトレースビューアを固定する。 playwright.config.tsでtrace: 'on-first-retry'を設定します。CIで不安定なテストが失敗した場合、ネットワーク呼び出し、DOMスナップショット、コンソールログの完全なタイムラインが得られます。API側にはapidog-cli --report htmlと組み合わせます。これらにより、UIが最初に壊れたのか、APIがずれたのかがわかります。
Apidogモックサーバーをオフライン実行に利用する。 Apidogは、OpenAPI仕様からワンクリックでモックサーバーを起動できます。バックエンドチームがデプロイ中であったり、ステージングデータベースがリセットされているときに、ローカル開発環境をそれに向けます。Playwrightスイートはモックに対して合格し、Apidogシナリオは並行して実際のバックエンドを検証します。このパターンに関する詳細は、モックが中心となるAI支援APIテスト生成についての記事をご覧ください。
リトライ回数を2回に制限する。 playwright.config.tsでretries: 2。テストが合格するために3回のリトライが必要な場合、それは不安定であり、深刻な問題があります。retries: 5でごまかしてはいけません。Apidogシナリオでも同様です。リクエストごとに最大retry: 1に設定してください。
スキーマのずれに対してクローズで失敗する。 Apidogがスキーマの不一致を検出した場合、デフォルトで非ゼロで終了します。警告を見過ごしてはいけません。ソフトフェイル期間を許可する必要がある場合は、ALLOW_SCHEMA_DRIFT=trueのような環境変数の背後に隠し、PRでその理由を説明するコメントを必須とします。
優先度別にテストをタグ付けする。 ステートフルなフローにはPlaywrightのtest.describe.configure({ mode: 'serial' })を使用し、その他のテストには@smoke、@regression、@nightlyのタグを付けます。すべてのプッシュでスモークテストを実行し、メインへのPRでリグレッションテストを実行し、夜間にはApidogの全シナリオスイートを実行します。これにより、カバレッジを失うことなくCI時間を節約できます。
避けるべきよくある間違い:
status === 200のみをアサートする。少なくとも1つのボディフィールドチェックを追加してください。- フィクスチャにベアラー(Bearer)トークンをハードコードする。
beforeAllを使用して新しいトークンを取得してください。 - PlaywrightとApidogが異なるフィクスチャファイルをインポートすることを許す。信頼できる情報源は一つだけです。
- 「UIツールで十分だから」といってCIでApidog CLIをスキップする。それは違います。CLIこそがビルドを失敗させるものです。
page.routeスタブを実際のAPIテストの代替として扱う。それらは分離のためであり、カバレッジのためではありません。
AIでテストを生成しているチーム向けには、AIエージェントAPIのテスト方法ガイドが、特別な注意が必要な非決定論的ケースをカバーしています。
代替ツールとツールの比較
ブラウザテストと並行してAPIを検証できるツールはいくつかあります。主要な選択肢を比較します。
| スタック | 強み | 弱み | 最適な用途 |
|---|---|---|---|
Playwright単体 (request フィクスチャ) |
単一ツール、高速、スイートにネイティブ | 浅いスキーマ検証、連鎖シナリオなし、エラーパスのカバーが弱い | 小規模チーム、シンプルなAPI |
| Playwright + Postman | 成熟したPostmanエコシステム、Newman CLI | 2つの情報源、PostmanコレクションがOpenAPIから乖離する可能性、コラボレーションに費用がかかる | すでにPostmanを深く利用しているチーム |
| Playwright + Apidog | 単一のOpenAPIソース、スキーマ検証、モック、CI用CLI、設計優先ワークフロー | 習得すべきツールが2つ、仕様に対する厳格さが求められる | 仕様駆動で網羅的なテストを求めるチーム |
| Cypress + cy-api プラグイン | Cypressユーザーには馴染み深い | Cypressはブラウザ内でのみ動作。APIテストが制限される。プラグインの完成度が低い場合がある。 | 既存のCypressコードベース |
| Pact (消費者駆動型契約) | サービス間の強力な契約保証 | 学習曲線が急、ブローカーインフラが必要、UIには焦点を当てていない | 多くの内部APIコンシューマーを持つマイクロサービス組織 |
古いSOAP時代のツールから移行する場合、SoapUI Groovyスクリプトの代替とReadyAPIの代替に関する記事が移行パスをカバーしています。ローカル優先のワークフローについては、RESTクライアントVSCode拡張機能を読む価値があります。
Playwright + Apidogの組み合わせは、OpenAPI仕様を持ち、複数のサービスを出荷し、UIとAPIの両方の退行をキャッチする単一のCIパイプラインを、エンジニア一人あたり2つのSaaSシートに費用を支払うことなく構築したいチームにとって勝利です。
実世界のユースケース
Eコマースのチェックアウト。 小売チームはカートから確認までのフローにPlaywrightテストを実行し、支払い意図、不正チェック、在庫減数APIチェーンにはApidogシナリオを実行します。支払いゲートウェイがレスポンスフィールドをerror_codeからerrorCodeに切り替えた際、Apidogは90秒でそれを捕捉しました。Playwrightであれば、一般的な「チェックアウト失敗」画面が表示され、トリアージに数時間かかったでしょう。
チャートデータを含むSaaSダッシュボード。 B2B分析製品は、PlaywrightスナップショットでUIレンダリングを検証し、Apidogを使用して集計エンドポイントが正しい合計、パーセンタイル、時間バケットシリーズを返すことをアサートします。p99レイテンシエンドポイントがサイレントに外れ値を削除していたバグはAPI層で捕捉されました。チャートは正常に見えていたのです。
Webhook駆動型ワークフロー。 フィンテックチームは、ユーザー向けポータルにPlaywrightを使用し、Webhook配信、リトライロジック、べき等性にApidogシナリオを使用します。Apidogのスクリプトは、重複するWebhook IDが拒否されること、署名が検証されること、および最終的な整合性ウィンドウが30秒以内であることを検証します。
結論
Playwrightはブラウザフローに優れていますが、深いAPIテストのために構築されているわけではありません。これをApidogと組み合わせることで、次のメリットが得られます。
- 両方のスイート間のコントラクトとしての1つのOpenAPI仕様。
- テストデータが乖離することのない共有フィクスチャ。
- ステータスコードだけでなく、すべてのエンドポイントでのスキーマレベルの検証。
- オフライン開発のためのモックサーバー。
- UIとAPIの両方の退行で失敗する単一のCIパイプライン。
- Playwrightでのネットワークインターセプション、Apidogでの深いシナリオチェーン。
- 明確な所有権:UIエンジニアはPlaywrightの仕様を、APIエンジニアはApidogのシナリオを担当します。
チェックアウトやサインアップのような、重要な旅の一つから始めてください。Playwrightのフィクスチャを設定し、対応するApidogシナリオを構築し、CIで両方を実行します。そこから広げていきましょう。Apidogをダウンロードし、OpenAPI仕様をインポートすれば、今日最初のシナリオを実行できるでしょう。
ボタン
FAQ
ApidogなしでPlaywrightテストでAPIを検証できますか? はい、Playwrightのrequestフィクスチャと手動のexpect呼び出しを使用すれば可能です。ステータスコードといくつかのボディフィールドはカバーできます。しかし、スキーマ検証、連鎖シナリオ、モック、大規模なエラーパスのカバレッジについては、Apidogのような専用ツールの方が高速で、誤検出も少なくなります。QAエンジニア向けAPIテストツールの比較でトレードオフをご確認ください。
このセットアップを使用するにはOpenAPI仕様が必要ですか? フルにメリットを享受するには必要です。仕様がない場合でも、PlaywrightとApidogを並行して実行できますが、共通の情報源を失い、例のペイロードを2か所で管理する必要があります。既存のルートから仕様を生成するには1~2日かかります。
両方のツールで認証をどのように処理しますか? beforeAllステップを使用して認証エンドポイントから新しいトークンを取得し、それをPlaywrightフィクスチャとApidog環境変数に保存します。テスト実行ごとにトークンをローテーションすることで、古いトークンが不安定な動作を引き起こすのを防ぎます。
ApidogシナリオはPlaywrightを完全に置き換えられますか? いいえ。ApidogはAPIワークフローに優れていますが、ブラウザをレンダリングしません。UIのアサーション(表示されるテキスト、レイアウト、クリックフロー)にはPlaywrightが依然として必要です。これら2つのツールは異なる側面をカバーしています。
バックエンドに安定したステージング環境がない場合はどうすればよいですか? Apidogに組み込まれているモックサーバーを使用してください。ワンクリックでOpenAPI仕様からステートフルなモックを起動し、仕様で定義された例のレスポンスを返します。PlaywrightスイートとApidogシナリオの両方がモックに対して合格し、ステージングが正常になったら実際のバックエンドに切り替えます。
スイートが成長してもCIを高速に保つにはどうすればよいですか? テストを優先度でタグ付けし、すべてのプッシュで@smokeのみを実行します。メインへのPRでは完全なリグレッションとApidogシナリオスイートを実行し、夜間スケジュールでも実行します。Playwrightはworkers: 4で並列化し、ApidogシナリオはCLIの--parallelフラグで並列化します。
CIで有料のApidogプランが必要ですか? Apidog CLIは、シナリオ実行のためにシートライセンスなしでローカルおよびCIで実行されます。大規模に採用する前に、現在の料金ページを確認してください。無料ティアはほとんどの小規模チームをカバーします。
