Đối với những bạn là người viết những test cases test automation đầu tiên, thì việc xác định được locator để tương tác lên các web elements cũng là một điều tương đối khó khăn. Thậm chí nếu bạn đã có kinh nghiệm với automation thì liệu chiến lược xác định locator của bạn đã là tốt nhất chưa? Trong bài này chúng ta hãy đi tìm hiểu cách để định ra một locator tốt nhé.
Vậy như thế nào là một cách xác định locator tốt? Không có locator nào là hoàn hảo, chỉ có locator phù hợp với những tiêu chí mà bạn đang muốn hướng đến. Nhiều người (team) sẽ có tiêu chí xác định locator như: xác định được locator nhanh nhất, chỉ cần locator hoạt động để test case thực thi thành công là được, v.v. Nhưng với tôi, ưu tiên hàng đầu vẫn là làm sao để locator hoạt động ổn định nhất có thể, giảm thiểu thấp nhất xác suất locator bị ảnh hưởng khi cấu trúc trang thay đổi. Điều này sẽ giúp giảm thiểu chi phí bảo trì, cập nhật locator. Trong nội dung bài viết này, tôi sẽ trình bày chiến lược chọn locator dựa trên các tiêu chí vừa đề cập.
Ưu tiên xác định locator bằng id
Tại sao bạn nên ưu tiên xác định locator của element bằng thuộc tính id?
- id của element thường là duy nhất, giúp bạn xác định chính xác element mong muốn.
- id của element thường ít bị thay đổi khi developer thực hiện refactor, giúp bạn tránh được việc phải update automation code.
- id locator ngắn gọn, dễ xác định, dễ đọc.
- id locator được hầu hết các test automation framework hỗ trợ.
Ví dụ: Làm sao để xác định phần tử Dog
trong đoạn HTML như bên dưới? Với Protractor framework, chúng ta có thể sử dụng cách xác định bằng id như sau:
HTML
<ul id="pet_id">
<li id="dog_id">Dog</li>
<li id="cat_id">Cat</li>
</ul>
Test code:
// Returns the web element for Dog
var dog = element(by.id('dog_id'));
Một số thuộc tính khác để xác định locator
Nếu element bạn đang cần tìm không tồn tại id thì chúng ta có thể xem xét đến những thuộc tính khác của element như: name, href, value, v.v.
Điều quan trọng nhất trước khi chọn thuộc tính để xác định locator là: xem xét tính duy nhất (unique) của thuộc tính. Điều này nhằm tránh trùng với một element khác có thuộc tính với giá trị tương tự, giúp chúng ta xác định chính xác element mong muốn.
Mỗi test automation framework sẽ hỗ trợ việc xác định locator bằng các thuộc tính khác nhau. Dưới đây, tôi xin lấy ví dụ xác định locator bằng một vài thuộc tính như: name, link text, partial link text trên WebdriverIO framework.
Name
<!-- HTML -->
<input type="text" name="username" value="" placeholder="Login Name">
// Locator
const name = $('[name="username"]')
Link text
<!-- HTML -->
<a href="https://www.cybozu.vn">Cybozu</a>
// Locator
const link = $('=Cybozu')
Partial Link Text
<!-- HTML -->
<a href="https://www.cybozu.vn">Cybozu</a>
// Locator
const link = $('*=bozu')
Những cách xác định locator này có những ưu điểm là: ngắn gọn, cú pháp đơn giản dễ sử dụng, ít bị ảnh hưởng khi thay đổi cấu trúc HTML. Khác với id, các thuộc tính như name, link text, v.v. thường không duy nhất trên một trang web. Do đó, nếu bạn đảm bảo được tính duy nhất của chúng, hoàn toàn có thể ưu tiên sử dụng.
CSS Selector và XPath
Nhiều trường hợp xác định locator bằng các thuộc tính của element như: id, text, link, tag name, v.v. là bất khả thi. Khi đó, CSS Selector hoặc XPath sẽ là giải pháp cho bạn.
CSS Selector và XPath sử dụng cú pháp (syntax) riêng để xác định locator. Chúng sử dụng sự kết hợp của tag name, các thuộc tính của elements, quan hệ giữa các elements (child, parent) để xác định locator. Điều tuyệt vời nhất là: cả hai giải pháp đều hỗ trợ được hầu hết các bài toán xác định locator.
Trước tiên, để quyết định nên sử dụng XPath hay CSS Selector, chúng ta hãy xem qua một số điểm khác nhau của hai loại này nhé:
Dựa vào bảng 1, nếu bạn có kinh nghiệm sử dụng cả CSS Selector và XPath, thì nên ưu tiên dùng CSS Selector để tận dụng ưu điểm đơn giản, thời gian thực thi nhanh. Mặt khác, bạn đã quen thuộc với XPath và chỉ có nhu cầu viết test code cho một loại browser thì cứ việc sử dụng XPath. Bạn cũng có thể sử dụng kết hợp cả hai trong dự án của mình.
Đối với CSS Selector và XPath, thường có hai trường phái để xác định locator:
Kiểu “chặt chẽ”
Locator được xác định theo tuần tự parent/child của các HTML tags.
Ví dụ:
- Xpath:
/body/div[1]/div/div[1]/a
- CSS Selector:
div > div > div > ul > li > span > a
Tôi gọi cách xác định này là “chặt chẽ” vì tính chính xác cao, không xác định nhầm lẫn nhiều elements. Nhưng cũng chính vì thế nó phụ thuộc chặt chẽ vào cấu trúc HTML. Khi có một thay đổi nhỏ của HTML thì locator sẽ không còn hoạt động được nữa. Ngoài ra, với cách xác định này locator thường sẽ dài, phức tạp.
Kiểu “lỏng lẻo”
Dùng các syntax của XPath hoặc CSS Selector để tìm kiếm element phù hợp.
Ví dụ:
- XPath:
//*[@text='value']
- CSS Selector:
#Add_button
Kiểu này được gọi là “lỏng lẻo” do nó không có sự liên kết giữa các HTML tags. Cách xác định này thường dẫn đến khả năng không chính xác cao hơn nếu chúng ta xử lý không hợp lý. Tuy nhiên kiểu này có ưu điểm là ít bị ảnh hưởng hơn khi HTML thay đổi và locator ngắn gọn hơn.
Tuỳ trường hợp, chúng ta còn có thể sử dụng kết hợp hai kiểu này. Ví dụ: /html/body/div/div/div//a[@title="Add"]
Để sử dụng CSS Selector và XPath hiệu quả, sau đây tôi trình bày một số kỹ thuật chung để xác định locator bằng hai loại này. Các ví dụ bên dưới được viết theo syntax XPath.
Khoanh vùng phạm vi tìm kiếm
Bước đầu tiên trong xác định locator bằng CSS Selector và XPath là: khoanh vùng phạm vi tìm kiếm element (vùng tìm kiếm). Tại sao cần khoanh vùng tìm kiếm? Hãy xem ví dụ dưới đây để hiểu rõ hơn:
Chúng ta cần xác định locator cho element-1 của hình bên dưới:
element-1 và element-2 có HTML giống nhau như sau:
<a href="https://cybozu.com/users/cybozu">cybozu</a>
Do đó, để xác định element-1 chúng ta cần khoanh vùng tìm kiếm. Ở đây, “vùng tìm kiếm” là element-3 trên hình 1.0, có HTML như sau:
<div class="comment_main_grn" id="thread_comment_2">
<a href="https://cybozu.com/users/cybozu">cybozu</a>
</div>
Sau khi xác định được vùng tìm kiếm, element-1 dễ dàng xác định được bằng Xpath như sau: //*[@id=”thread_comment_2”]/a
Mục đích và đặc điểm của việc khoanh vùng tìm kiếm là:
- Tìm phạm vi gần với element cần tìm nhất. Phạm vị này đảm bảo xác định được chính xác element, không nhầm lẫn với element khác tương tự trên trang. Có thể tạm gọi phạm vi này là “cột mốc“
- Element cần tìm là con nằm trong “cột mốc“
- Cột mốc nên là id hoặc unique thuộc tính để đảm bảo nó là duy nhất.
Hạn chế thấp nhất việc sử dụng nhiều cấp
Việc sử dụng locator với nhiều cấp /parent/child/
sẽ tăng độ phụ thuộc của locator vào cấu trúc HTML. Chúng ta có thể kết hợp các thuộc tính của element để tạo một tập hợp tìm kiếm hiệu quả.
Ví dụ: Chúng ta có cấu trúc HTML như sau:
<header class="header">
<div class="column-01">
<a class="button-01" href="/next/">Next</a>
</div>
<div class="column-02">
<a class="button-02" href="/previous/">Previous</a>
</div>
</header>
Để xác định button-02
, chúng ta có thể sử dụng locator một trong hai cách như sau:
- locator-01:
//header[@class=”header”]//a[@class=”button-02”]
- locator-02
//header[@class=”header”]/div[2]/a[@class=”button-02”]
Giả sử HTML bị thay đổi do bên phía developer thực hiện refactor:
<header class="header">
<div class="column-01">
<a class="button-01" href="/next/">Next</a>
</div>
<div class="column-011">
<a class="button-011" href="/today/">Today</a>
</div>
<div class="column-02">
<a class="button-02" href="/previous/">Previous</a>
</div>
</header>
Khi đó, locator-2 sẽ không còn hoạt động được. Qua ví dụ này, chúng ta nên ưu tiên sử dụng locator hạn chế thấp nhất quan hệ nhiều cấp, phụ thuộc quá chặt chẽ vào HTML.
Tận dụng sự kết hợp unique text để xác định locator
Trên trang web hiển thị hai loại text: text mặc định với giá trị cố định của ứng dụng và input text do người dùng nhập vào.
Đối với element chứa text cố định, chúng ta có thể dùng text kết hợp với các element “cột mốc” để xác định locator cho element đó. Ví dụ locator cho “Post” button: //*[@id="thread_comment_button"]//*[text()="Post"]
Đối với element chứa input text, chúng ta có thể chủ động ở bước khởi tạo input data để làm cho chúng trở nên unique. Như ví dụ bên dưới, khi thực hiện đến phần input text, chúng ta nên thêm vào random string để làm cho input text trở nên unique. Sau đó, sử dụng những unique input text này trong xác định locator.
Trong hình 4.0, để xác định locator của “Subject”, chúng ta có thể sử dụng XPath sau:
//*[text()="Testing Subject -abcd12132ewew"]
Trên đây, tôi trình bày 3 kỹ thuật mà bạn có thể sử dụng để xác định locator bằng CSS Selector và XPath một cách nhanh chóng và hiệu quả. Bạn có thể kết hợp 3 kỹ thuật cùng lúc, hoặc tùy chọn sử dụng sao cho phù hợp.
Kết
Hãy cố gắng tìm cách để xác định locator một cách đơn giản nhất, ngắn gọn, dễ hiểu nhưng vẫn giữ được tiêu chí ban đầu mà mình đã đặt ra cho việc xác định locator. Riêng với tôi, tiêu chí đó là là đảm bảo tính ổn định của hệ thống khi có sự thay đổi của HTML.