Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Playwright — newer modern alternative

Mở đầu — vì sao bài này quan trọng

Nếu bạn đã theo dõi khóa học đến đây, bạn đã biết Selenium là "ông tổ" của UI automation, và Cypress là làn gió mới giúp việc viết test nhanh và ổn định hơn nhiều. Nhưng năm 2020, Microsoft mở mã nguồn một công cụ mới tên là Playwright, và chỉ trong vài năm, nó đã trở thành lựa chọn được nhiều đội QA hiện đại ưu tiên hàng đầu — kể cả những đội đang dùng Cypress.

Tại sao lại có thêm một công cụ nữa khi thị trường đã đông đúc? Câu trả lời nằm ở chính đội ngũ tạo ra Playwright: phần lớn họ là những kỹ sư từng xây dựng Puppeteer tại Google, sau đó chuyển sang Microsoft. Họ hiểu rất rõ điểm mạnh và điểm yếu của các công cụ đi trước, đặc biệt là những rào cản kiến trúc mà Cypress không thể vượt qua được. Playwright được thiết kế ngay từ đầu để "học từ điểm yếu của Cypress" — hỗ trợ đa trình duyệt thật sự, đa tab, đa ngôn ngữ lập trình, và đặc biệt là cơ chế auto-wait thông minh giúp giảm mạnh flaky test.

Với bạn — một QA đang muốn theo nghề automation ở Việt Nam — hiểu Playwright không còn là "nice to have" mà đang dần trở thành yêu cầu trong nhiều tin tuyển dụng SDET, nhất là ở các công ty product và outsourcing lớn như FPT Software, KMS Technology, hay các startup fintech. Bài này sẽ giúp bạn nắm chắc Playwright là gì, khác Cypress ra sao, và biết khi nào nên chọn nó.

Khái niệm cốt lõi

Playwright là một thư viện automation cho phép bạn điều khiển trình duyệt (Chromium, Firefox, WebKit) bằng code để mô phỏng hành vi người dùng thật: click, gõ phím, điều hướng, kiểm tra nội dung. Về mục đích, nó giống Selenium và Cypress. Nhưng cách nó vận hành bên trong thì rất khác.

Kiến trúc: giao tiếp qua một kết nối duy nhất

Selenium điều khiển trình duyệt qua giao thức WebDriver — mỗi lệnh là một request HTTP riêng, khá chậm. Cypress thì chạy bên trong trình duyệt (in-browser), đây là điểm mạnh giúp nó nhanh nhưng cũng là gốc rễ của mọi giới hạn: vì chạy trong browser nên Cypress bị "nhốt" trong sandbox của tab hiện tại.

Playwright chọn con đường thứ ba: nó giao tiếp với trình duyệt qua một kết nối WebSocket duy nhất, dùng các giao thức debug gốc của từng engine (như Chrome DevTools Protocol). Cách này cho tốc độ gần bằng Cypress nhưng không bị nhốt trong browser, nên Playwright có thể làm những việc Cypress không làm nổi.

Auto-wait — trái tim chống flaky

Điểm khiến nhiều người "yêu" Playwright là cơ chế auto-wait. Trước mỗi hành động (ví dụ click một nút), Playwright tự động kiểm tra hàng loạt điều kiện: phần tử đã gắn vào DOM chưa, có hiển thị không, có ổn định (không đang animation) không, có bị phần tử khác che không, có enable không. Chỉ khi tất cả thỏa mãn nó mới thực hiện. Điều này loại bỏ phần lớn nhu cầu viết sleep hay wait thủ công — nguyên nhân số một gây flaky test.

Đa trình duyệt và đa tab thật sự

Cypress trong nhiều năm chỉ hỗ trợ tốt Chromium và không xử lý được nhiều tab hay nhiều domain trong một test. Playwright hỗ trợ cả ba engine trình duyệt lớn: Chromium (Chrome, Edge), Firefox, và WebKit (engine của Safari) — đây là điểm cực kỳ quan trọng nếu sản phẩm của bạn có nhiều người dùng iPhone/Safari, vốn rất phổ biến ở Việt Nam. Ngoài ra Playwright xử lý mượt mà nhiều tab, nhiều cửa sổ, iframe, và popup.

Đa ngôn ngữ

Cypress chỉ hỗ trợ JavaScript/TypeScript. Playwright có binding chính thức cho JavaScript/TypeScript, Python, Java, và C#/.NET. Đây là lợi thế lớn cho các đội mà tester quen Python hoặc dự án dùng .NET.

So sánh nhanh Cypress vs Playwright

Tiêu chíCypressPlaywright
Trình duyệtChromium tốt, WebKit hạn chếChromium, Firefox, WebKit đầy đủ
Ngôn ngữChỉ JS/TSJS/TS, Python, Java, C#
Đa tab / đa domainKhó/hạn chếHỗ trợ tự nhiên
Auto-waitCó, mạnh hơn
Chạy song songCần Cypress Cloud (trả phí)Miễn phí, sẵn có
Kiến trúcChạy trong browserKết nối ngoài qua WebSocket
Cú phápChuỗi command (thiên async ẩn)async/await tường minh
Debug trực quanTime-travel tốtTrace Viewer rất mạnh
Một điểm khác biệt về "cảm giác code": Cypress dùng chuỗi command kiểu cy.get(...).click() và ẩn đi tính bất đồng bộ. Playwright dùng async/await tường minh — bạn viết await page.click(...). Cách này thẳng thắn hơn và dễ debug hơn với ai đã quen JavaScript hiện đại.

Tình huống thực tế

Ví dụ 1 — Sàn TMĐT chuyển từ Cypress sang Playwright vì Safari

Một công ty thương mại điện tử tại TP.HCM (giả định tên "ShopViet", quy mô ~150 nhân sự) có bộ test UI viết bằng Cypress khoảng 400 test case. Vấn đề: dữ liệu analytics cho thấy 38% khách hàng của họ dùng iPhone với Safari, nhưng Cypress không kiểm thử được WebKit một cách tin cậy. Kết quả là nhiều lỗi CSS chỉ xảy ra trên Safari — ví dụ nút "Thanh toán" bị lệch và không click được — lọt lên production, gây rớt đơn hàng.

Đội QA quyết định migrate sang Playwright trong 6 tuần. Vì cú pháp khá tương đồng (đều dựa trên locator và auto-wait), việc chuyển đổi phần lớn là cơ học. Sau khi hoàn tất, họ chạy cùng bộ test trên cả ba engine. Ngay tuần đầu, Playwright phát hiện 7 lỗi chỉ xuất hiện trên WebKit mà trước đó hoàn toàn "vô hình". Bài học: nếu tập người dùng của bạn có tỷ lệ Safari/iOS cao — điều rất phổ biến ở thị trường Việt Nam — khả năng test WebKit thật của Playwright là lý do đủ mạnh để chọn nó.

Ví dụ 2 — Fintech xử lý luồng đa tab đăng nhập OAuth

Một startup fintech ở Hà Nội xây dựng ví điện tử, có luồng đăng nhập bằng tài khoản đối tác: người dùng bấm "Đăng nhập với đối tác", một tab/popup mới mở ra ở domain khác để xác thực, sau đó quay lại app. Đội QA từng dùng Cypress và... bó tay, vì Cypress không điều khiển được popup ở domain thứ hai trong cùng một test. Họ phải tách nhỏ và test thủ công phần này — tốn khoảng 3 giờ mỗi lần release.

Chuyển sang Playwright, họ dùng cơ chế bắt sự kiện tab mới (context.waitForEvent('page')) để nắm lấy popup, thao tác trên đó rồi quay lại tab chính — tất cả trong một test tự động liền mạch. Luồng test end-to-end 3 giờ thủ công rút xuống còn 90 giây tự động. Bài học: với những luồng đa tab, đa domain — rất thường gặp trong thanh toán và OAuth — Playwright giải quyết được đúng điểm mà Cypress bế tắc về mặt kiến trúc.

Ví dụ 3 — Đội Python không muốn học JavaScript

Một đội QA outsourcing (giả định "QALab", ~20 người) chủ yếu là tester có nền Python, đang viết API test bằng pytest. Họ muốn thêm UI automation nhưng ngại phải học cả một hệ sinh thái JavaScript mới nếu chọn Cypress. Playwright có binding Python chính thức, nên họ viết UI test bằng playwright + pytest — dùng luôn kiến thức pytest fixtures và cấu trúc dự án sẵn có. Thời gian onboard cho một tester mới giảm từ ~3 tuần (nếu học Cypress/JS) xuống còn ~5 ngày. Bài học: ngôn ngữ đội bạn đang thành thạo là một yếu tố lựa chọn công cụ rất thực tế, và Playwright cho bạn sự linh hoạt đó.

Hướng dẫn từng bước

Dưới đây là cách bắt đầu với Playwright bằng JavaScript/TypeScript — cách phổ biến nhất.

Bước 1 — Khởi tạo dự án. Trong thư mục dự án, chạy:

npm init playwright@latest

Lệnh này sẽ hỏi bạn dùng JS hay TS, tên thư mục test, có thêm GitHub Actions workflow không, và tự động tải về ba engine trình duyệt. Đây là điểm tiện lợi: bạn không phải cài driver riêng như Selenium.

Bước 2 — Hiểu cấu trúc. Playwright tạo file playwright.config.ts (nơi khai báo trình duyệt cần test, base URL, số lần retry...) và thư mục tests/ chứa file test mẫu.

Bước 3 — Viết test đầu tiên. Một test cơ bản trông như sau:

import { test, expect } from '@playwright/test';

test('người dùng đăng nhập thành công', async ({ page }) => { await page.goto('https://shopviet.example.com/login'); await page.getByLabel('Email').fill('user@example.com'); await page.getByLabel('Mật khẩu').fill('MatKhau123'); await page.getByRole('button', { name: 'Đăng nhập' }).click(); await expect(page.getByText('Xin chào')).toBeVisible(); });

Chú ý getByRolegetByLabel — đây là các locator gợi ý ưu tiên của Playwright, dựa trên vai trò accessibility và nhãn, giúp test bền hơn và giống cách người dùng thật nhìn giao diện. (Chi tiết về chiến lược locator bạn đã học ở bài riêng.)

Bước 4 — Chạy test.

npx playwright test

Mặc định Playwright chạy headless trên cả ba trình duyệt và chạy song song. Muốn xem trình duyệt thật, thêm --headed; muốn debug từng bước, dùng --debug.

Bước 5 — Xem báo cáo và Trace. Sau khi chạy:

npx playwright show-report

Nếu một test fail, hãy bật trace trong config (trace: 'on-first-retry'). Trace Viewer là "vũ khí bí mật" của Playwright: nó ghi lại toàn bộ dòng thời gian của test dưới dạng snapshot DOM tương tác, cho bạn tua tới lui xem đúng khoảnh khắc lỗi, kèm network và console. Đây là công cụ debug trực quan mạnh nhất trong các framework UI hiện nay.

Bước 6 — Dùng Codegen để học nhanh. Chạy npx playwright codegen shopviet.example.com, một cửa sổ trình duyệt mở ra và Playwright tự sinh code khi bạn thao tác thật. Đây là cách tuyệt vời để người mới học cú pháp locator đúng.

Lỗi thường gặp & mẹo

Quên await. Vì Playwright dùng async tường minh, thiếu await trước một action là lỗi phổ biến nhất. Test có thể "pass" nhầm hoặc chạy sai thứ tự. Hãy bật ESLint rule cho Playwright để cảnh báo sớm.

Lạm dụng waitForTimeout. Nhiều người mang thói quen sleep từ Selenium sang, viết await page.waitForTimeout(3000). Đừng làm vậy trừ khi bất đắc dĩ — nó vừa chậm vừa flaky. Hãy tin vào auto-wait và các web-first assertion như await expect(locator).toBeVisible(), chúng tự retry cho đến khi điều kiện đúng hoặc hết timeout.

Nhầm giữa expect thường và web-first assertion. expect(await locator.textContent()).toBe('x') chỉ kiểm tra một lần, dễ flaky. Trong khi await expect(locator).toHaveText('x') sẽ tự động chờ và thử lại. Ưu tiên dạng thứ hai.

Locator quá cụ thể theo CSS/XPath. Playwright khuyến khích getByRole, getByText, getByTestId. Locator bám vào cấu trúc HTML hay class CSS dễ vỡ khi UI đổi. Với phần tử động, thêm data-testid trong code frontend là cách bền nhất.

Test bị chia sẻ state. Mỗi test nên độc lập. Tận dụng browserContext — mỗi test chạy trong context riêng, cookie và storage tách biệt, tránh test này ảnh hưởng test kia. Playwright còn cho lưu trạng thái đăng nhập (storageState) để không phải login lại mỗi test, tăng tốc đáng kể.

Mẹo vàng: dùng tính năng retry ở cấp config (retries: 2 trong CI) kết hợp trace: 'on-first-retry'. Cách này giúp bạn không bỏ sót flaky test nhưng vẫn có trace đầy đủ để điều tra nguyên nhân.

Bài tập thực hành

  • Cài đặt và chạy. Tạo một dự án Playwright mới bằng npm init playwright@latest. Chạy bộ test mẫu trên cả ba trình duyệt và mở báo cáo HTML. Ghi lại thời gian chạy trên từng engine.
  • Viết test đăng nhập. Chọn một trang web công khai có form đăng nhập (hoặc site demo như the-internet.herokuapp.com). Viết một test đăng nhập dùng getByLabel, getByRole và một web-first assertion. Cố tình nhập sai mật khẩu và viết thêm test kiểm tra thông báo lỗi hiển thị.
  • Thử Codegen. Dùng npx playwright codegen để tự sinh một kịch bản tìm kiếm sản phẩm trên một trang TMĐT bất kỳ. Quan sát loại locator mà Playwright chọn, rồi tự chỉnh lại cho gọn hơn.
  • Khám phá Trace Viewer. Cố tình làm một test fail (ví dụ đổi text assertion thành sai). Bật trace, chạy lại, mở Trace Viewer và tua tới khoảnh khắc fail. Viết 3–4 câu mô tả bạn thấy gì.
  • Suy nghĩ chiến lược. Giả sử bạn là QA lead ở một startup fintech có 40% người dùng iOS và luồng thanh toán mở popup sang domain đối tác. Viết một đoạn ngắn (khoảng 150 từ) lập luận vì sao bạn chọn Playwright thay vì Cypress cho dự án này.

Tóm tắt

Playwright là công cụ UI automation do Microsoft mở mã năm 2020, được xây bởi chính những người từng làm Puppeteer, với mục tiêu rõ ràng là học từ điểm yếu của các công cụ đi trước — đặc biệt là Cypress. Những khác biệt cốt lõi cần nhớ: kiến trúc kết nối ngoài qua WebSocket giúp nó nhanh nhưng không bị nhốt trong browser; hỗ trợ đầy đủ ba engine Chromium, Firefox và WebKit (quan trọng cho tập người dùng Safari/iOS đông ở Việt Nam); hỗ trợ bốn ngôn ngữ JS/TS, Python, Java, C#; xử lý đa tab và đa domain tự nhiên; auto-wait mạnh cùng web-first assertion giúp giảm mạnh flaky test; chạy song song miễn phí; và Trace Viewer là công cụ debug trực quan hàng đầu.

Điều đó không có nghĩa Playwright luôn thắng Cypress trong mọi tình huống — Cypress vẫn có cộng đồng lớn, trải nghiệm dev thân thiện và hệ sinh thái plugin phong phú. Nhưng khi bạn cần đa trình duyệt thật, đa tab, linh hoạt ngôn ngữ, hay khả năng song song không tốn phí, Playwright thường là lựa chọn xứng đáng. Hãy tự tay cài đặt, viết vài test và chơi với Trace Viewer — bạn sẽ nhanh chóng cảm nhận vì sao nó được nhiều đội QA hiện đại tin dùng.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi