Playwright là gì? Tại sao cần viết test case đúng cách?
Playwright là framework automation testing mã nguồn mở do Microsoft phát triển, hỗ trợ kiểm thử trên nhiều trình duyệt (Chromium, Firefox, WebKit) với một codebase duy nhất. Không chỉ mạnh mẽ về kỹ thuật, Playwright còn cung cấp API trực quan giúp tester và developer viết test case nhanh, ổn định và dễ bảo trì.
Tuy nhiên, viết test case với Playwright không chỉ đơn thuần là “ghi lại thao tác rồi chạy”. Một test case hiệu quả đòi hỏi tư duy Test Design rõ ràng, xác định đúng điều cần kiểm tra, trước khi chuyển sang viết Automation Script.
Test Design là gì? Tại sao phải làm trước khi code?
Test Design là quá trình xác định:
- Mục tiêu kiểm thử (What to test?)
- Điều kiện đầu vào (Test data, preconditions)
- Kết quả mong đợi (Expected outcomes)
- Các bước thực hiện (Steps to reproduce)
Bỏ qua bước này dẫn đến các test case bị trùng lặp, thiếu coverage, khó debug khi fail, và quan trọng hơn là không phản ánh đúng yêu cầu nghiệp vụ.
Cấu trúc một Test Case chuẩn với Playwright
1. Đặt tên test có ý nghĩa
// ❌ Không rõ ràng
test('test login', async ({ page }) => { ... });
// ✅ Rõ ràng, đọc như tài liệu
test('should display error message when login with wrong password', async ({ page }) => { ... });Nguyên tắc đặt tên: [hành vi mong đợi] + [ngữ cảnh/điều kiện]
2. Áp dụng mô hình AAA: Arrange, Act, Assert
Đây là cấu trúc nền tảng của mọi test case tốt:
test('should add item to cart successfully', async ({ page }) => {
// ARRANGE — Chuẩn bị dữ liệu và trạng thái ban đầu
await page.goto('/products');
await page.waitForSelector('.product-list');
// ACT — Thực hiện hành động cần kiểm thử
await page.click('[data-testid="add-to-cart-btn"]');
// ASSERT — Kiểm tra kết quả
await expect(page.locator('.cart-count')).toHaveText('1');
});3. Sử dụng Locator Strategy đúng cách
Playwright khuyến khích sử dụng user-facing locators thay vì CSS/XPath phức tạp:
// ❌ Dễ vỡ khi UI thay đổi
await page.click('#app > div.main > button:nth-child(3)');
// ✅ Bền vững, gần với cách người dùng tương tác
await page.getByRole('button', { name: 'Đăng nhập' }).click();
await page.getByLabel('Email').fill('user@example.com');
await page.getByTestId('submit-btn').click();Thứ tự ưu tiên locator trong Playwright:
getByRole(): Tốt nhất, theo ARIA rolegetByLabel(): Cho form inputsgetByText():Cho text contentgetByTestId(): Khi cần selector ổn địnhlocator()với CSS/XPath: Cuối cùng mới dùng
4. Tổ chức test với describe và beforeEach
import { test, expect } from '@playwright/test';
test.describe('Tính năng Đăng nhập', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/login');
});
test('đăng nhập thành công với thông tin hợp lệ', async ({ page }) => {
await page.getByLabel('Email').fill('admin@test.com');
await page.getByLabel('Mật khẩu').fill('Admin@123');
await page.getByRole('button', { name: 'Đăng nhập' }).click();
await expect(page).toHaveURL('/dashboard');
});
test('hiển thị lỗi khi mật khẩu sai', async ({ page }) => {
await page.getByLabel('Email').fill('admin@test.com');
await page.getByLabel('Mật khẩu').fill('wrong-password');
await page.getByRole('button', { name: 'Đăng nhập' }).click();
await expect(page.getByRole('alert')).toContainText('Sai tên đăng nhập hoặc mật khẩu');
});
});5. Data-Driven Testing: Test nhiều bộ dữ liệu
const loginTestCases = [
{ email: '', password: 'valid', expected: 'Email không được để trống' },
{ email: 'invalid-email', password: 'valid', expected: 'Email không hợp lệ' },
{ email: 'user@test.com', password: '', expected: 'Mật khẩu không được để trống' },
];
for (const tc of loginTestCases) {
test(`validation: ${tc.expected}`, async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill(tc.email);
await page.getByLabel('Mật khẩu').fill(tc.password);
await page.getByRole('button', { name: 'Đăng nhập' }).click();
await expect(page.getByRole('alert')).toContainText(tc.expected);
});
}6. Page Object Model (POM): Tái sử dụng và bảo trì dễ dàng
Khi dự án lớn lên, Page Object Model là pattern không thể thiếu:
// pages/LoginPage.ts
export class LoginPage {
constructor(private page: Page) {}
async goto() {
await this.page.goto('/login');
}
async login(email: string, password: string) {
await this.page.getByLabel('Email').fill(email);
await this.page.getByLabel('Mật khẩu').fill(password);
await this.page.getByRole('button', { name: 'Đăng nhập' }).click();
}
async getErrorMessage() {
return this.page.getByRole('alert').textContent();
}
}
// tests/login.spec.ts
test('đăng nhập thành công', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login('admin@test.com', 'Admin@123');
await expect(page).toHaveURL('/dashboard');
});
Các lỗi phổ biến khi viết test case với Playwright
| Lỗi | Hậu quả | Cách khắc phục |
|---|---|---|
Dùng page.waitForTimeout(3000) | Test chậm, không ổn định | Dùng waitForSelector, expect().toBeVisible() |
Không có data-testid | Locator bị vỡ khi refactor UI | Thống nhất với developer đặt test ID |
| Test phụ thuộc vào thứ tự chạy | Flaky tests | Mỗi test phải độc lập, tự chuẩn bị data |
| Assert quá nhiều trong 1 test | Khó debug khi fail | 1 test — 1 assertion chính |
| Bỏ qua negative cases | Thiếu coverage | Luôn viết test cho edge cases và lỗi |
Thêm một đoạn văn bản ở đây. Nhấp vào ô văn bản để tùy chỉnh nội dung, phong cách phông chữ và màu sắc của đoạn văn của bạn.
Checklist viết Test Case với Playwright
Trước khi commit test, kiểm tra các tiêu chí sau:
- Tên test mô tả rõ hành vi cần kiểm tra
- Test có cấu trúc Arrange – Act – Assert
- Không dùng
waitForTimeoutcứng - Locator theo
getByRole,getByLabel, hoặcgetByTestId - Test chạy độc lập, không phụ thuộc test khác
- Có cả positive case và negative case
- Dữ liệu test không hardcode trong production logic
- Test pass ổn định sau 3 lần chạy liên tiếp
Tổng kết: Các bước phải làm để viết test case với Playwright
1. Phân tích requirement → Xác định Test Condition
2. Thiết kế Test Case → Đặt tên, input, expected output
3. Chọn Locator Strategy → Ưu tiên user-facing selectors
4. Viết script theo AAA → Arrange, Act, Assert
5. Áp dụng POM → Tái sử dụng, dễ maintain
6. Review & Refactor → Đảm bảo stability và readability
Bạn muốn thực hành Playwright từ cơ bản đến nâng cao?
Khóa học Playwright chuyên sâu của CO-WELL sẽ giúp bạn:
Nắm vững Test Design Thinking — biết cái gì cần test trước khi code
Viết Automation Script chuẩn với TypeScript + Playwright
Áp dụng Page Object Model và Data-Driven Testing thực chiến
Tích hợp test vào CI/CD pipeline
Xử lý các tình huống phức tạp: iFrame, Upload/Download, API Mocking
Sau khóa học có project thực tế để đưa vào CV và luyện tập phỏng vấn theo kỹ thuật STAR.
Khai giảng: 27/5/2025
Số lượng học viên có giới hạn — Đăng ký sớm để đảm bảo suất học!


