Chapter 17 · APIRequestContext and API Testing
Chapter goals: Use Playwright's built-in HTTP client
APIRequestContextto test REST APIs directly, and combine "API seeding + UI verification" into the fastest test shape.
17.1 Why Not Just Use requests
Playwright ships a full HTTP client, APIRequestContext, with official use cases:
- Test server APIs directly;
- Prepare server-side state via API before visiting the web app;
- Verify server-side post-conditions after browser operations.
Compared to requests/httpx, its unique advantage is same-origin sharing with the browser context: it automatically carries the same Cookies/auth state as the page (the storage_state from Chapter 9 is directly reusable), and cleans up uniformly with the context — the UI and API channels are natively打通.
17.2 Creating an Independent API Context
The官方 pattern: session-scoped fixture + playwright.request.new_context():
# conftest.py
import os
from typing import Generator
import pytest
from playwright.sync_api import Playwright, APIRequestContext
API_TOKEN = os.getenv("GITHUB_API_TOKEN", "")
@pytest.fixture(scope="session")
def api_request_context(
playwright: Playwright,
) -> Generator[APIRequestContext, None, None]:
headers = {
# Declare version per GitHub spec
"Accept": "application/vnd.github.v3+json",
"Authorization": f"token {API_TOKEN}",
}
request_context = playwright.request.new_context(
base_url="https://api.github.com",
extra_http_headers=headers,
)
yield request_context
request_context.dispose() # Clean up connections uniformlybase_url lets all subsequent requests use relative paths; get/post/put/delete methods return APIResponse with useful attributes: .ok (2xx check), .status, .json(), .text().
17.3 Writing a Set of API Cases
Skeleton from the official GitHub Issues example:
# tests/test_issues_api.py
GITHUB_USER = "your-user"
GITHUB_REPO = "api-test-repo"
def test_should_create_bug_report(api_request_context: APIRequestContext):
data = {"title": "[Bug] report 1", "body": "Bug description"}
new_issue = api_request_context.post(
f"/repos/{GITHUB_USER}/{GITHUB_REPO}/issues", data=data
)
assert new_issue.ok # Assert 2xx
issues = api_request_context.get(f"/repos/{GITHUB_USER}/{GITHUB_REPO}/issues")
assert issues.ok
issue = [i for i in issues.json() if i["title"] == "[Bug] report 1"][0]
assert issue["body"] == "Bug description"Pair with session-scoped setup/teardown to manage the existence of "the resource under test" (create the repo first, delete after):
@pytest.fixture(scope="session", autouse=True)
def create_test_repository(api_request_context: APIRequestContext):
new_repo = api_request_context.post("/user/repos", data={"name": GITHUB_REPO})
assert new_repo.ok
yield # ---- all tests run between here ----
deleted = api_request_context.delete(f"/repos/{GITHUB_USER}/{GITHUB_REPO}")
assert deleted.ok17.4 API Seeding + UI Verification: The Fastest Shape
The most efficient E2E pattern: seed data via API (fast, deterministic), verify via UI (human-validated):
def test_product_visible_after_api_create(page, api_request_context):
# Fast API seed
resp = api_request_context.post("/api/products", json={"name": "Widget", "price": 9.9})
product = resp.json()
# UI verification
page.goto(f"/products/{product['id']}")
expect(page.get_by_role("heading", name="Widget")).to_be_visible()
expect(page.get_by_text("$9.90")).to_be_visible()This cuts test time by 60–80% compared to UI-only data creation, while keeping the human-meaningful UI assertion.
17.5 Chapter Summary
APIRequestContextis Playwright's built-in HTTP client; shares auth state with the browser;- Session-scoped fixture +
dispose()is the standard lifecycle pattern; - API seeding + UI verification is the fastest E2E shape;
- Combine with
storage_state(Ch 9) for authenticated API calls.
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. What is the key advantage of APIRequestContext over requests.http?
2. What does APIResponse.ok represent?
3. Why is API seeding + UI verification faster than UI-only data creation?
4. When should you call request_context.dispose()?
🛠️ Hands-On Exercises
- Write a session-scoped
api_request_contextfixture for a public REST API (e.g., JSONPlaceholder); create a resource via POST and assert its ID in the response. - Combine API seeding with a UI test: create a product via API, visit the storefront, and assert the product appears with correct price.
- Add a session-scoped teardown that deletes the created resource via DELETE; verify it no longer appears in a subsequent GET.
Proceed to Chapter 18: Async API and FastAPI Integration Testing.