Playwright trên production — và lúc Selenium vẫn thắng
Playwright và Selenium không phải cuộc thi “tool nào hot”. Đây là chuyện chờ DOM, lúc 2 giờ sáng còn gì để mở, và constraint nào bạn không thương lượng được.

Hai giờ sáng. CI đỏ. Ticket ghi “flaky”. Không ai nhớ test đó click cái gì. Screenshot 200px. Team đoán như xem tranh trừu tượng.
Đó không phải chuyện “chọn thư viện sai”. Đó là kiến trúc: nói chuyện với browser thế nào, chờ thế nào, và lúc fail còn artifact nào — sự thật, không phải cảm giác.
Playwright (Microsoft) và Selenium (hệ sinh thái WebDriver) đều điều khiển browser thật. Chúng không cùng một mô hình. Gọi cả hai là “tool UI test” rồi thay qua lại là cách đội thu thập flake, không phải coverage.
Bạn đang mua cái gì?
Selenium 2026 vẫn là stack W3C WebDriver: code test → process driver (ChromeDriver, geckodriver, …) → browser. Giao thức là lệnh HTTP: tìm element, click, lấy text. Grid dàn session ra nhiều máy. Appium ngồi cạnh cùng ý tưởng cho native mobile. Cược: portability — nhiều ngôn ngữ, nhiều browser, nhiều vendor, dễ thuê người đã biết WebDriver.
Playwright là một engine với binding TypeScript/JavaScript, Python, Java, .NET. Nó mở (hoặc nối) Chromium, Firefox, WebKit bằng đường gần debug protocol của browser hơn là REST driver. Cược: determinism — auto-wait, context tách, trace, và giả định bạn chịu sở hữu phiên bản browser.
Công ty đã chốt WebDriver trên giấy? Selenium là mặc định.
SPA rerender liên tục mà suite phải xanh? Playwright là mặc định.
Hầu hết team có cả hai. Phần còn lại của bài: chọn mà không tự lừa mình.
Hai đường nói chuyện với browser

Hình 1. Trái: mỗi lệnh WebDriver là một round-trip. Phải: Playwright giữ kết nối, auto-wait trên đường nóng, context A/B/C trong một process.
WebDriver lệch kênh. Test gửi JSON HTTP tới driver, driver nói với browser. Mỗi hành động một vòng. “Đã visible chưa?” là vòng nữa — trừ khi bạn tự bọc wait. Dễ hiểu, dễ scale bằng Grid. Cũng dễ đua: DOM đã chạy giữa find và click. Như gửi thư cho người đang đổi nhà: thư tới, chuông cửa đã chuyển tầng.
Playwright giữ kết nối bền và auto-wait trên hot path. Click không phải “tìm rồi click”. Là “chờ locator nhận được click, rồi mới click”, timeout đặt một lần. Selector là locator — query lười, đánh lại đến khi được hoặc hết giờ — không phải snapshot findElement một phát rồi cầu nguyện.
Thêm browser context: cookie, storage, session tách trong một browser. Test song song không bắt buộc một browser đầy đủ mỗi worker. Selenium tách bằng session mới — đắt hơn nếu không cẩn.
Selenium 4 không kẹt năm 2014: relative locator, cửa sổ/iframe ổn hơn, CDP tùy driver. WebDriver BiDi là nỗ lực ngành cho ống hai chiều hiện đại. Việc đó quan trọng. Nó chưa bằng gói wait + trace “mở hộp là dùng” của Playwright quý này. Roadmap protocol ≠ suite tuần sau.
Nhà máy flake: chờ
Hầu hết chuyện “Selenium flaky” là chuyện wait. Implicit wait giấu race. WebDriverWait đúng nhưng dài. Deadline tới thì Thread.sleep. Load CI đổi nhịp — suite nói dối, bạn tin.

Hình 2. Sleep / implicit wait tạo gai thời gian. Auto-wait đi attached → visible → stable → click — vẫn cần timeout thật, không phải timeout laptop.
Playwright không làm bạn miễn nhiễm. Nó biến mặc định thành thứ senior đã viết tay: attached, visible, stable, enabled, nhận event. Bạn vẫn phải:
- Timeout theo trang tệ nhất production, không theo máy dev (máy dev là dối trá có Wi‑Fi)
- Assert kết quả (URL, text, network, cây a11y) — không assert class CSS triển khai tuần này
- Kỷ luật với
force: truevàwaitForTimeout— đó là sleep mặc vest
Team Selenium đã có wait helper + data-testid sẽ không xanh magically vì rewrite Playwright. Họ được lớp wait ngắn hơn. Product không có hook ổn định thì cả hai tool đều cào đầm lầy. Tool không cứu selector div:nth-child(3).
// Playwright: chờ đúng điều kiện, không sleep
await page.getByRole("button", { name: "Thanh toán" }).click();
await expect(page).toHaveURL(/\/checkout\/done/);
2 giờ sáng: một file hay một cuộc khai quật
Đây là chỗ Playwright thường trả tiền migration.
Fail: Playwright dump trace (DOM snapshot, screenshot, network, console, source) — mở Trace Viewer. Runner được thiết kế để tự giải thích. HTML report, video, inspector/codegen cùng một hộp. Như hộp đen máy bay, không phải “ai đó nhớ có chụp hình không”.
Selenium debug là lắp ghép: listener chụp hình, Allure hoặc ReportPortal, video node Grid, log browser nếu driver chịu. Có thể rất hay. Không bao giờ là một flag. Người mới vào khảo cổ mỗi lần — năm tab, ba mật khẩu dashboard.

Hình 3. Một artifact vs năm mảnh: screenshot, Allure, video Grid, log. Pipeline già thì đừng vứt. Chưa có pipeline thì đừng dựng Allure trước — lấy trace + suite nhỏ.
Browser, Safari, điện thoại
Playwright ship WebKit (cùng Firefox, Chromium). Đó không phải “Safari trên Mac phòng họp”. Nhưng là WebKit mở, automate được mà nhiều CI từng không có. Selenium + Safari/WebDriver trên macOS vẫn thắng khi bug là browser Apple, không phải “na ná WebKit”. Khách kêu Safari, bạn đừng chỉ Chromium rồi gọi là xong.
Chrome ≠ Chromium — cả hai thế giới. Pháp lý / support đòi đúng browser khách cài: Grid, cloud (BrowserStack, Sauce, LambdaTest), lab máy. Playwright nối remote được; hệ sinh thái Selenium dày hơn. Đừng giả vờ Playwright thay device lab.
Mobile: Appium vẫn là câu WebDriver cho native. Playwright mạnh viewport web mobile và một phần WebView — không thay Appium. Team lai: Appium native, Playwright web. Tách đó tỉnh, không phải thiếu hoài bão.
Ngôn ngữ, thuê người, Grid
| Selenium | Playwright | |
|---|---|---|
| Cược | Chuẩn + fleet | Control plane đóng gói |
| Wait mặc định | Tự viết / sleep | Auto-wait |
| Debug | Tự ráp | Trace Viewer |
| Scale quen | Grid 2015-cơ | Worker + shard CI |
| Native app | Appium cạnh nhà | Không phải Appium |
| Hiring | Mọi ngôn ngữ WebDriver | Ít binding, first-class |
Grid (hoặc cloud Grid) vẫn pattern “500 session, năm version browser, ba OS”. Playwright parallel = worker và CI shard, cộng remote tùy chọn. Scale được — tự thiết kế hoặc mua vendor. Không được cơ nhớ Grid miễn phí.
Thêm Playwright khi đang chạy Grid = hai chính sách version, hai kho secret, hai runbook “sao CI đỏ”. Nước đi tỉnh: Playwright cho UI sản phẩm mới, Selenium cho suite Java cũ đến khi khai tử. Chạy đôi mãi là cách platform mục — và vẫn ship bug khách thấy bằng một click.
Mạng, login, mép component
route / mock / HAR: test là công dân mạng — stub dependency, chờ request, assert mutation. Selenium làm được qua CDP hoặc proxy. Playwright giả định bạn sẽ làm.
storageState (cất cookie/localStorage, dùng lại) giết cả lớp “login mỗi test”. Selenium serialize cookie được; Playwright biến thành recipe mặc định.
request context cạnh UI tiện. Không phải lý do xóa contract test HTTP ở Go/Java. Dùng để cắm state rồi assert UI — không phải suite contract duy nhất.
Nhanh — có caveat
Playwright thường nhanh vì: không thuế HTTP từng lệnh, reuse browser, context, wait thông minh (ít sleep). Grid cũng nhanh khi node nóng và test batch tốt.
Đừng chọn tool vì blog ghi “nhanh gấp 3”. Đo suite của bạn: wall clock CI, flake 30 ngày, thời gian chẩn đoán một fail. Suite chậm mà xanh thắng suite nhanh mà đỏ. Tốc độ không cứu được sleep(5000).
Selenium vẫn thắng khi
- WebDriver là chuẩn org — Grid chung, Appium, hợp đồng vendor, team Java.
- Browser bạn không kiểm soát — kiosk, engine lạ, Safari/IE-class (hiếm, vẫn thật).
- Suite đã xanh — giá rewrite > giá flake. Wedge Playwright trên mặt mới, không port big-bang.
- RFP đòi W3C trên giấy hơn là trace. Lạ — vẫn gặp. Giấy thắng file
.ziptrace.
Playwright là kiến trúc tốt hơn khi
- SPA hiện đại (React, Vue, island Astro…) và flake đang là wait.
- Muốn một toolchain: runner, trace, codegen, nhiều engine trên CI — không ráp sáu jar.
- Context + storageState khớp cách nghĩ tenant / user (SaaS).
- Team thật sự mở trace. Tool không ai mở là đồ trang trí — đắt hơn Allure bạn cũng không mở.
Migrate mà không thành rewrite
Đừng dịch 2.000 test Selenium từng dòng. Bạn sẽ port flake — cùng bug, syntax mới, ego cao hơn.
- Đóng băng suite cũ làm cổng chất lượng; chỉ thêm khi cháy production.
- Journey mới, tối hạn, viết Playwright: login, trả tiền, báo cáo sếp nhìn.
- Chung hook (
data-testidhoặc role + tên). - Chuyển journey chỉ khi xóa bản Selenium trong cùng PR.
- Một dashboard “đường khách thấy” — không một dashboard một tool.
Đó là ADR: Playwright cho UI automation mới; Grid đến khi native/Appium và Java legacy nghỉ; xem lại khi chi phí Grid hoặc flake vượt chi phí chạy đôi.
Takeaway
Selenium là chuẩn và một fleet. Playwright là control plane đóng gói cho browser. Cái trước thắng hệ sinh thái và lực hút hiring. Cái sau thắng wait mặc định, trace, và test hình SPA.
Chọn constraint không thương lượng — Grid đã trả tiền, hoặc CI đang nói dối — rồi tối ưu cái đó. Trộn cả hai không có lối thoát là cách nuôi hai nền tảng automation… và vẫn ship bug khách thấy bằng một click.
Found this insightful? Like or share with your team:
Spread good engineering craft & architecture lessons.
Comments
Email is not published. Keep it professional.