Playwright là gì? Từ E2E Testing đến AI Test Agents (2026)
1. Playwright là gì?
Playwright là framework E2E testing mã nguồn mở do Microsoft phát triển (2020), bởi team từng xây dựng Puppeteer.
Nó tích hợp sẵn:
- test runner
- assertions
- test isolation
- parallel execution
- debugging tools
→ tất cả trong một package duy nhất
Hỗ trợ:
- Chromium, Firefox, WebKit
- Windows, Linux, macOS
- Headless / headed
- Mobile emulation
Khác với Selenium (WebDriver), Playwright: → giao tiếp trực tiếp với browser qua DevTools Protocol → nhanh hơn và ổn định hơn
2. Core capabilities
Auto-wait (loại bỏ flaky test)
Playwright tự động chờ element:
- visible
- stable
- enabled
await page.getByRole('button', { name: 'Submit' }).click();
Không cần:
sleep()waitForSelector()
Assertions cũng auto-retry:
await expect(page).toHaveURL('/dashboard');
Test Isolation
Mỗi test chạy trong một BrowserContext riêng:
- không share cookies
- không share localStorage
- không share session
→ tương đương incognito → chạy song song không xung đột
Web-first Assertions
Assertions sẽ: → tự wait cho đến khi condition đúng
await expect(locator).toBeVisible();
→ giảm flaky test đáng kể
Locator (ưu tiên accessibility)
page.getByRole('button', { name: 'Login' })
thay vì:
page.locator('.btn-primary')
→ test resilient hơn khi UI thay đổi
Cross-browser
projects: [
{ name: 'chromium' },
{ name: 'firefox' },
{ name: 'webkit' }
]
→ viết 1 lần, chạy nhiều browser
3. Dev experience & tooling
Trace Viewer
npx playwright show-trace trace.zip
- timeline toàn bộ test
- DOM snapshot
- network / console log
→ debug deterministic
UI Mode
npx playwright test --ui
- watch mode
- time-travel debugging
- pick locator trực tiếp
Codegen
npx playwright codegen https://your-app.com
→ generate test từ thao tác thật
HTML Report
npx playwright show-report
Screenshots & Video
use: {
screenshot: 'only-on-failure',
video: 'retain-on-failure'
}
4. Advanced features
Network Interception
await page.route('**/api/**', route => {
route.fulfill({ body: JSON.stringify({ mock: true }) });
});
API Testing
const res = await request.get('/api/users');
Multi-tab / Multi-window
const [newPage] = await Promise.all([
context.waitForEvent('page'),
page.click('a[target=_blank]')
]);
Parallel & Sharding
npx playwright test --shard=1/3
Fixtures
test('example', async ({ page, authUser }) => {
// custom fixture
});
Authentication reuse
await context.storageState({ path: 'auth.json' });
5. Ưu & nhược điểm
Ưu điểm
- Nhanh, ổn định (DevTools Protocol)
- Built-in đầy đủ
- Parallel native
- Debug mạnh (trace viewer)
Nhược điểm
- Ecosystem chưa lớn bằng Selenium
- Cần làm quen locator mới
6. Playwright MCP — AI điều khiển browser
Playwright MCP server cho phép LLM (AI) tương tác với web thông qua Model Context Protocol.
Cách hoạt động:
- AI không nhìn screenshot hay pixel
- AI đọc accessibility snapshot — cấu trúc text mô tả toàn bộ UI
Ví dụ, AI nhìn thấy trang web như thế này:
- heading "todos" [level=1]
- textbox "What needs to be done?" [ref=e5]
- listitem:
- checkbox "Toggle Todo" [ref=e10]
- text: "Buy groceries"
Mỗi element có một ref (reference ID). AI dùng ref để tương tác:
ref=e5→ type text vào textboxref=e10→ check checkbox
→ không cần vision model, không đoán tọa độ → nhanh, chính xác, hoạt động với mọi MCP client (VS Code, Cursor, Kiro...)
7. Playwright Test Agents — AI tự viết test
Playwright Test Agents đưa AI vào toàn bộ lifecycle của testing.
Bao gồm 3 agents:
- Planner — khám phá app, sinh test plan
- Generator — viết code test từ plan
- Healer — tự sửa test khi fail
Flow:
seed → planner → generator → healer
Seed file
Bạn chỉ cần viết 1 test cơ bản — đưa AI vào đúng trang cần test:
test('seed', async ({ page }) => {
await page.goto('/');
// login nếu cần
// verify đã vào được app
});
Planner sẽ chạy seed này để "bước vào" ứng dụng, rồi từ đó khám phá tiếp.
Planner — tạo test plan
Planner mở browser, đi qua từng trang, đọc menu, form, button, table... rồi sinh ra file markdown mô tả các test scenarios:
## 1. Add Valid Todo
**Steps:**
1. Click "What needs to be done?" input
2. Type "Buy groceries"
3. Press Enter
**Expected:**
- Todo xuất hiện trong list
- Counter shows "1 item left"
Bạn review plan này, thêm edge cases nếu cần, rồi chuyển cho generator.
Generator — viết code test
Generator đọc plan, mở browser thật, thực hiện từng step, verify selector trực tiếp trên UI, rồi sinh code .spec.ts:
test('Add Valid Todo', async ({ page }) => {
const input = page.getByRole('textbox', { name: 'What needs to be done?' });
await input.fill('Buy groceries');
await input.press('Enter');
await expect(page.getByText('Buy groceries')).toBeVisible();
await expect(page.getByText('1 item left')).toBeVisible();
});
Healer — self-healing test
Khi test fail (UI đổi, selector cũ, timing issue...), healer tự:
- replay failing step
- inspect UI hiện tại
- tìm element tương đương
- patch code (update locator, thêm wait...)
- chạy lại
Nếu feature thực sự bị lỗi (không phải do test sai): → healer skip test thay vì sửa vô nghĩa
8. Authentication trong thực tế
Khi app cần đăng nhập, test cần login trước khi chạy. Playwright có 2 cách tùy theo mode:
CLI mode (npx playwright test)
Login 1 lần, lưu session ra file, các test sau dùng lại — không cần login lại:
// auth.setup.ts — chạy 1 lần trước tất cả test
setup('login', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Username').fill('test');
await page.getByLabel('Password').fill('test');
await page.getByRole('button', { name: 'Login' }).click();
// Lưu cookies + localStorage ra file
await page.context().storageState({ path: 'playwright/.auth/user.json' });
});
Config để các test tự load session đã lưu:
projects: [
{ name: 'setup', testMatch: /.*\.setup\.ts/ },
{
name: 'chromium',
use: { storageState: 'playwright/.auth/user.json' },
dependencies: ['setup'],
},
]
MCP mode (AI agents chạy test đơn lẻ)
Khi agents chạy test qua MCP, không có project config → không có session file. Dùng custom fixture để tự detect và auto-login:
export const test = base.extend({
page: async ({ page }, use) => {
const originalGoto = page.goto.bind(page);
page.goto = async (url, options) => {
const res = await originalGoto(url, options);
if (page.url().includes('/login')) {
await page.getByLabel('Username').fill('test');
await page.getByLabel('Password').fill('test');
await page.getByRole('button', { name: 'Login' }).click();
await page.waitForLoadState('domcontentloaded');
}
return res;
};
await use(page);
},
});
→ CLI mode: login 1 lần, reuse session → MCP mode: tự login khi cần
9. Test có side-effect — chạy lại vẫn pass
Một số test thực hiện hành động thay đổi dữ liệu thật:
- hủy đơn hàng
- xóa tài khoản
- cancel điểm
Vấn đề: lần đầu chạy thì pass, nhưng lần 2 dữ liệu đã bị thay đổi → test fail.
Cách xử lý: kiểm tra trạng thái dữ liệu trước khi thực hiện.
test('cancel order', async ({ page }) => {
await page.goto('/orders');
// Tìm đơn hàng chưa cancel
const cancelBtn = page.getByRole('button', { name: 'Cancel' });
if (await cancelBtn.count() === 0) {
// Không còn đơn nào để cancel → skip thay vì fail
test.skip(true, 'No orders available to cancel');
return;
}
// Có đơn → thực hiện cancel
await cancelBtn.first().click();
await expect(page.getByText('Cancelled')).toBeVisible();
});
→ lần 1: cancel thành công → lần 2: detect không còn data → skip → test luôn green, chạy bao nhiêu lần cũng được
10. Kết luận
Playwright là E2E testing framework hiện đại:
- nhanh
- ổn định
- đa trình duyệt
Playwright MCP mở ra hướng: → AI điều khiển browser một cách deterministic
Playwright Test Agents đưa testing lên một level mới: → AI tự viết test → AI tự debug → AI tự sửa lỗi
Workflow mới:
seed → AI generate → AI fix
Với các hệ thống lớn hoặc cần scale automation, Playwright + Test Agents gần như là lựa chọn mặc định hiện tại.