API Testing With Playwright: A Guide for QA Engineers and Developers
Playwright enables unified API and UI testing with support for all HTTP methods, authentication, retries, and mocks—helping build reliable backend tests fast.
Join the DZone community and get the full member experience.
Join For FreeEnsuring the quality and reliability of backend services through API testing is as crucial as testing the user interface. APIs act as the backbone for data exchange between different components and systems. Without robust API tests, defects can propagate unnoticed, leading to faulty features and unhappy users.
Playwright, widely acclaimed as a next-generation browser automation framework, extends its capabilities beyond UI testing to support comprehensive API testing. By leveraging Playwright for API testing, QA engineers and developers benefit from a unified framework that seamlessly integrates API and UI tests. This article explores how to effectively use Playwright for API testing—from basics to advanced techniques—while offering practical advice and real-world examples.
Why API Testing Matters
APIs power almost every modern application — mobile, web, cloud, and IoT. Testing APIs offers several advantages:
- Faster feedback than UI testing because APIs bypass the graphical layer.
- Early detection of bugs in backend logic or integrations.
- More stable tests unaffected by UI changes.
- Validation of business logic, security, and data consistency.
Effective API testing ensures that the entire application ecosystem communicates correctly and reliably.
Why Use Playwright for API Testing
Playwright was designed with modern web application testing in mind. Its API testing features provide several key benefits:
- Unified framework: Write both UI and API tests using the same language, tooling, and test runner.
- Support for all HTTP methods: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD.
- Network interception and mocking: Simulate API responses or failures to isolate tests.
- Parallel execution: Run API tests concurrently for speed and efficiency.
- Built-in assertion library: Make your API test assertions concise and readable.
By consolidating API and UI testing, teams reduce complexity and maintain consistency.
Setting Up Playwright for API Testing
If you already have Playwright installed, you can skip this section. Otherwise, follow these steps:
bashnpm init playwright@latest # Follow prompts to install Playwright and dependencies
Create a new folder for your project, initialize, and install dependencies:
bashmkdir playwright-api-testing cd playwright-api-testing npm init -y npm install @playwright/test npx playwright install
Basic API Testing Examples
Playwright exposes a request API to create HTTP request contexts. Here’s how to use it.
GET Request Example
import { test, expect, request } from '@playwright/test';
test('GET user details API test', async () => {
const apiContext = await request.newContext();
const response = await apiContext.get('https://jsonplaceholder.typicode.com/users/1');
expect(response.status()).toBe(200);
const body = await response.json();
expect(body).toHaveProperty('id', 1);
expect(body).toHaveProperty('username', 'Bret');
});
POST Request with Payload and Headers
import { test, expect, request } from '@playwright/test';
test('POST create user API test', async () => {
const apiContext = await request.newContext();
const payload = {
name: 'Alice',
email: '[email protected]',
};
const response = await apiContext.post('https://jsonplaceholder.typicode.com/users', {
data: payload,
headers: {
'Content-Type': 'application/json',
},
});
expect(response.status()).toBe(201);
const body = await response.json();
// Optional: JSONPlaceholder returns more than just name/email, so partial match is best
expect(body).toMatchObject(payload);
await apiContext.dispose();
});
PUT, PATCH, DELETE Requests
Modify or delete resources with Playwright’s API calls:
// PUT - Update resource
await apiContext.put('/resource/1', {
data: updatedData
});
// PATCH - Partial update
await apiContext.patch('/resource/1', {
data: patchData
});
// DELETE - Remove resource
await apiContext.delete('/resource/1');
Advanced API Testing
Authentication (OAuth, JWT, API Keys)
Many APIs require authentication tokens. Playwright supports sending tokens in headers.
test('Authenticated GET request', async () => {
const apiContext = await request.newContext({
extraHTTPHeaders: {
'Authorization': `Bearer YOUR_JWT_TOKEN`
}
});
const response = await apiContext.get('/secure-endpoint');
expect(response.status()).toBe(200);
});
To automate token retrieval, chain a login API call before testing protected endpoints.
Handling Cookies and Sessions
Cookies can be managed by Playwright’s request context or page context for UI tests.
await apiContext.setCookies([
{
name: 'session',
value: 'abc123',
domain: 'example.com'
}
]);
Error Handling and Retries
Playwright allows you to implement retries for flaky API calls.
test('Retry example', async ({}, testInfo) => {
for (let i = 0; i < 3; i++) {
const response = await apiContext.get('/unstable-endpoint');
if (response.ok()) return;
await new Promise(r => setTimeout(r, 1000)); // wait and retry
}
testInfo.fail();
});
Integrating API and UI Testing
Playwright shines by allowing you to combine API and UI tests.
Setup Test Data via API Before UI Tests
test('Create user via API and verify in UI', async ({ page }) => {
const apiContext = await request.newContext();
const response = await apiContext.post('/users', {
data: { name: 'TestUser' }
});
expect(response.ok()).toBeTruthy();
await page.goto('/users');
await expect(page.locator('text=TestUser')).toBeVisible();
});
Mocking and Network Interception
Simulate API responses to test UI behavior under different conditions.
await page.route('**/api/data', route =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ key: 'mocked value' }),
})
);
Best Practices
- Reuse API contexts to optimize test speed.
- Use environment variables for URLs and tokens.
- Keep test data isolated and clean up after tests.
- Write clear assertions for status, headers, and payload.
- Leverage Playwright’s parallel testing for scalability.
- Use retries sparingly to avoid hiding real issues.
CI/CD Pipeline Integration
Integrate Playwright API tests into your pipeline:
- Use GitHub Actions, Jenkins, Azure Pipelines, etc.
- Run tests on push or PR events.
- Publish test reports and alerts.
Example GitHub Actions snippet:
name: Playwright Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm install
- run: npx playwright install
- run: npx playwright test
Case Study: Login API and Dashboard UI Verification
Imagine you have a login API and a dashboard UI page.
- Login API Call: Obtain auth token via API.
- Set Token in UI: Inject token into localStorage.
- Navigate UI: Go to dashboard and verify elements.
test('Login via API and verify dashboard', async ({ page, request }) => {
const response = await request.post('/api/login', {
data: { username: 'user', password: 'pass' }
});
const { token } = await response.json();
await page.addInitScript(token => {
localStorage.setItem('authToken', token);
}, token);
await page.goto('/dashboard');
await expect(page.locator('text=Welcome')).toBeVisible();
});
Troubleshooting Common Issues
- Flaky network requests: Use retries or mocks.
- Authentication failures: Check tokens and headers carefully.
- Timeouts: Adjust timeout values in Playwright config.
- Parsing errors: Validate JSON responses before use.
Summary and Conclusion
Playwright provides a powerful, flexible framework for API testing that complements UI automation. By mastering API testing with Playwright, QA professionals and developers can build more robust, maintainable, and faster test suites that cover the full application stack.
Opinions expressed by DZone contributors are their own.
Comments