Bạn hoàn toàn có thể test API với Playwright. Playwright cung cấp APIRequestContext để gửi HTTP request trực tiếp từ test, thứ mà Selenium bó tay.
Ví dụ
Ví dụ dưới đây là 1 bài toán cơ bản trong API testing: Login với Username và Password để lấy token, sau đó dùng token đó để GET số lượng bài viết, hoặc POST tạo bài viết mới cho 1 hệ thống blog cá nhân.
Cấu hình header dùng chung
Chúng ta có thể cấu hình những thành phần không đổi cho 1 API header tại file config như sau, cách thành phần này sẽ được tự động append vào header về sau:
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
extraHTTPHeaders: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
});*** Settings ***
Library RequestsLibrary
*** Variables ***
&{COMMON_HEADERS} Accept=application/json Content-Type=application/jsonBước 1: POST đăng nhập thông qua API
import { test, expect } from '@playwright/test';
test('đăng nhập và lấy token', async ({ request }) => {
const response = await request.post('/api/users/login', {
data: {
user: {
// 2 biến này có sẵn trong môi trường
email: process.env.API_EMAIL,
password: process.env.API_PASSWORD,
},
},
});
expect(response.status()).toBe(200);
expect(response.ok()).toBeTruthy();
const body = await response.json();
expect(body.user.token).toBeTruthy();
expect(body.user.email).toBe(process.env.API_EMAIL);
});*** Test Cases ***
Đăng Nhập Và Lấy Token
&{user}= Create Dictionary
... email=%{API_EMAIL}
... password=%{API_PASSWORD}
&{payload}= Create Dictionary user=${user}
${response}= POST
... ${BASE_URL}/api/users/login
... json=${payload}
... headers=&{COMMON_HEADERS}
... expected_status=200
Should Be Equal As Integers ${response.status_code} 200
${body}= Set Variable ${response.json()}
Should Not Be Empty ${body}[user][token]
Should Be Equal ${body}[user][email] %{API_EMAIL}response.status() trả status code cụ thể; response.ok() đúng với response từ 200 đến 299. Trong bài test thực tế nên kiểm tra status code chính xác theo API documentation, không chỉ kiểm tra chung chung 2xx.
Tạo 1 hàm helper đăng nhập dùng lại
Muốn tạo bài viết mới, hay get list bài viết thì đều cần token là tiền điều kiện. Vì vậy hãy tạo 1 hàm truyền tên đăng nhập và mật khẩu vào, sau đó trả ra token để có thể sử dụng:
async function loginAndGetToken(request): Promise<string> {
const response = await request.post('/api/users/login', {
data: {
user: {
email: process.env.API_EMAIL,
password: process.env.API_PASSWORD,
},
},
});
expect(response.status()).toBe(200);
return (await response.json()).user.token;
}Đăng Nhập Và Lấy Token
&{user}= Create Dictionary
... email=%{API_EMAIL}
... password=%{API_PASSWORD}
&{payload}= Create Dictionary user=${user}
${response}= POST
... ${BASE_URL}/api/users/login
... json=${payload}
... headers=&{COMMON_HEADERS}
... expected_status=200
RETURN ${response.json()}[user][token]Bước 2: GET danh sách bài viết với header Token
test('GET danh sách bài viết', async ({ request }) => {
const token = await loginAndGetToken(request);
const response = await request.get('/api/articles', {
headers: {
Authorization: 'Bearer ' + token,
},
params: { limit: 10, offset: 0 },
});
expect(response.status()).toBe(200);
const body = await response.json();
expect(Array.isArray(body.articles)).toBeTruthy();
expect(body.articlesCount).toBeGreaterThanOrEqual(0);
});*** Test Cases ***
GET Danh Sách Bài Viết
${token}= Đăng Nhập Và Lấy Token
&{headers}= Create Dictionary
... Authorization=Token ${token}
... Accept=application/json
&{params}= Create Dictionary limit=10 offset=0
${response}= GET
... ${BASE_URL}/api/articles
... headers=&{headers}
... params=&{params}
... expected_status=200
Should Be Equal As Integers ${response.status_code} 200
${body}= Set Variable ${response.json()}
Should Be True isinstance(${body}[articles], list)
Should Be True ${body}[articlesCount] >= 0Bước 3: POST tạo bài viết và verify response
test('POST tạo bài viết', async ({ request }) => {
const token = await loginAndGetToken(request);
const title = 'Bài viết mới ' + Date.now();
const response = await request.post('/api/articles', {
headers: {
Authorization: 'Bearer ' + token,
},
data: {
article: {
title: title ,
description: 'Bài viết được tạo bởi automated test',
body: 'Nội dung dùng cho bài học Playwright API testing.',
tagList: ['playwright', 'api-testing'],
},
},
});
expect(response.status()).toBe(201);
const body = await response.json();
expect(body.article.title).toBe(uniqueTitle);
expect(body.article.slug).toBeTruthy();
expect(body.article.tagList).toContain('playwright');
});*** Test Cases ***
POST Tạo Bài Viết
${token}= Đăng Nhập Và Lấy Token
${unique_title}= Catenate SEPARATOR= Playwright API ${SPACE} ${TEST NAME}
&{headers}= Create Dictionary
... Authorization=Token ${token}
... Content-Type=application/json
@{tags}= Create List playwright api-testing
&{article}= Create Dictionary
... title=${unique_title}
... description=Bài viết được tạo bởi automated test
... body=Nội dung dùng cho bài học Playwright API testing.
... tagList=${tags}
&{payload}= Create Dictionary article=${article}
${response}= POST
... ${BASE_URL}/api/articles
... headers=&{headers}
... json=${payload}
... expected_status=201
Should Be Equal As Integers ${response.status_code} 201
${body}= Set Variable ${response.json()}
Should Be Equal ${body}[article][title] ${unique_title}
Should Not Be Empty ${body}[article][slug]
Should Contain ${body}[article][tagList] playwrightNên kiểm tra những gì trong API response?
| Nhóm | Ví dụ |
|---|---|
| Status | GET thành công là 200; tạo thành công là 201 |
| Schema cơ bản | Field bắt buộc tồn tại và đúng kiểu |
| Business data | Các giá trị trả về là chính xác so với những giá trị gửi lên |
| Negative case | Token sai trả 401, body sai trả 422… không được trả 500 |



