Playwright locator: viết test form theo role và label để bớt phụ thuộc CSS

5 giờ tới · 7 phút đọc
Vấn đề với CSS selector trong test form
Khi viết automation test cho form đăng ký, đăng nhập hay checkout, cách phổ biến nhất là dùng CSS selector như input.form-control hay #email-field. Vấn đề? Dev đổi class hoặc refactor HTML, test gãy ngay - dù tính năng vẫn hoạt động đúng.
Đây là dạng flaky test phổ biến nhất trong web automation: test fail không phải vì bug, mà vì selector không còn khớp.
Playwright cung cấp hai locator được khuyến nghị trong tài liệu chính thức để giải quyết vấn đề này: getByRole() và getByLabel(). Cả hai đều dựa trên ngữ nghĩa HTML và ARIA - thứ ít thay đổi hơn class hay id trong quá trình refactor.
CSS selector gãy khi dev đổi class, locator theo role/label thì không
Lưu ý phiên bản: Bài này dùng Playwright từ v1.20 trở lên - phiên bản ổn định hóa API
getByRole,getByLabel. Kiểm tra phiên bản hiện tại tại tài liệu Locators chính thức của Playwright.
getByRole là gì và khi nào dùng
getByRole() tìm phần tử dựa trên ARIA role - vai trò ngữ nghĩa của phần tử theo chuẩn WAI-ARIA. Ví dụ: <button> có role button, <input type="text"> có role textbox, <a> có role link.
Cú pháp cơ bản:
Tham số name khớp với accessible name của phần tử - thường là label text, aria-label, hoặc nội dung button. Khớp không phân biệt hoa thường theo mặc định.
Accessible name lấy từ label, aria-label hoặc nội dung text của phần tử
Khi nào dùng getByRole?
- Button, link, checkbox, radio, combobox (select), dialog
- Bất kỳ phần tử nào có semantic role rõ ràng trong HTML
- Khi muốn test phản ánh đúng cách người dùng thực và screen reader tương tác với trang
Khi KHÔNG nên chỉ dùng getByRole:
- Phần tử dùng role tùy chỉnh không chuẩn (custom component thiếu ARIA)
- Trang dùng nhiều phần tử cùng role và không có
namephân biệt được
getByLabel là gì và khi nào dùng
getByLabel() tìm input được liên kết với một <label> cụ thể. Đây là cách tự nhiên nhất để locate field trong form vì nó phản ánh đúng cách người dùng nhìn form.
Cú pháp:
Playwright tìm label có text khớp, rồi trả về input liên kết qua for/id hoặc label bọc input trực tiếp:
Cả hai cách trên đều hoạt động với getByLabel('Email') và getByLabel('Mật khẩu').
getByLabel hoạt động với cả hai cách viết HTML label phổ biến
Khác biệt với getByRole:
getByLabelchuyên cho input fields trong formgetByRole('textbox', { name: 'Email' })vàgetByLabel('Email')thường ra cùng kết quả - chọn cái nào đọc tự nhiên hơn trong contextgetByLabelsẽ fail nếu input không có label liên kết đúng chuẩn (giả định minh họa: input thiếu label là lỗi accessibility luôn)
Ví dụ tối thiểu: test form đăng nhập
Dưới đây là ví dụ giả định minh họa - form HTML đơn giản và test Playwright tương ứng. Bạn có thể tự chạy để kiểm tra.
Form HTML mẫu (giả định):
Test Playwright (TypeScript):
Form đơn giản, test rõ ràng - không cần CSS selector nào
Kết quả mong đợi khi chạy đúng: Test pass, không có assertion error. Nếu label text không khớp chính xác, Playwright báo getByLabel('...') resolved to X elements hoặc no element found.
Cách chạy và cấu hình isolation
Cài đặt và chạy lần đầu:
Isolation: Playwright tạo browser context mới cho mỗi test theo mặc định - nghĩa là cookie, localStorage, session không bị chia sẻ giữa các test. Đây là isolation tự động, không cần cấu hình thêm.
Tuy nhiên nếu test dùng state chung (ví dụ: đăng nhập một lần rồi dùng cho nhiều test), bạn cần storageState:
Mỗi test có browser context riêng - isolation mặc định của Playwright
Cách tự kiểm tra isolation đang hoạt động:
Chạy hai test này theo thứ tự, cả hai phải pass.
Lỗi thường gặp và cách xử lý
1. getByLabel không tìm thấy phần tử
Nguyên nhân phổ biến nhất: label không liên kết đúng với input.
Nếu không thể sửa HTML (component của bên thứ ba), dùng getByPlaceholder hoặc getByRole với name lấy từ aria-label thay thế.
2. getByRole trả về nhiều phần tử
Xảy ra khi trang có nhiều button cùng text hoặc nhiều input cùng role mà không có name phân biệt. Fix:
3. Khớp text không chính xác
Theo mặc định name khớp substring không phân biệt hoa thường. Nếu cần khớp chính xác:
Ba lỗi hay gặp và cách fix tương ứng
4. Component thiếu ARIA attribute
Custom component (React, Vue) đôi khi render ra <div> không có role. Ví dụ giả định: <div class="custom-checkbox"> sẽ không có role checkbox trừ khi dev thêm role="checkbox" và aria-checked. Trường hợp này, báo dev fix hoặc tạm dùng locator('[data-testid="..."]') - nhưng cần thêm data-testid vào HTML.
