NỘI DUNG BÀI HỌC
✅Cách xác định Locators trên Appium Inspector
✅Cách record Locators trên Appium Inspector
✅Các dạng Locators được Appium Inspector hỗ trợ
✅Xác định locators dựa vào XPATH axes (tương đối)
✅Locators là gì?
Trong Test Automation trên giao diện UI thì Locators là cách để xác định và tương tác với các phần tử trên giao diện (UI elements) trong một ứng dụng di động hoặc website. Đây là một thành phần quan trọng để viết các bài kiểm thử tự động. Locators giúp bạn tìm kiếm các phần tử trên giao diện, ví dụ như button, input, checkbox, hoặc các thành phần khác.
Locator trên Mobile UI dùng Appium Inspector để xác định:
Locator trên Web UI dùng SelectorsHub để xác định:
✅Cách xác định Locators trên Appium Inspector
- Chọn tab mũi tên Select Elements.
- Click chọn element cần lấy locator, sẽ được gợi ý highlight màu vàng trên phần UI.
- Kiểm tra cây thư mục element vùng nằm giữa.
- Kiểm tra giá trị các loại locators vùng nằm bên phải.
- Copy giá trị dán vào code Appium Java để chạy test automation.
✅Cách record Locators trên Appium Inspector
- Chọn tab Start Recording
- Click chọn element cần thao tác
- Điền text đối với element là dạng input hoặc textbox
- Click nút Send Keys hoặc Clear đối với textbox
- Click chọn nút Tab để click vào element
- Click chọn tab Recorder, code sẽ được tự động sinh ra tương ứng với các thao tác trên (Code Snippet)
- Chọn loại ngôn ngữ lập trình cần generate code
- Khi đó sẽ thấy được các dạng locator mà tools bắt được theo gợi ý của tools Appium Inspector.
✅Các dạng Locators được Appium Inspector hỗ trợ
Dưới đây là các loại locators mà Appium hỗ trợ:
-
ID
- Dùng để xác định một phần tử dựa trên thuộc tính
resource-id
(trên Android) hoặcaccessibilityIdentifier
(trên iOS). - Ví dụ:
- Dùng để xác định một phần tử dựa trên thuộc tính
-
Accessibility ID
- Được sử dụng để tìm phần tử thông qua
content-desc
(Android) hoặcaccessibilityIdentifier
(iOS). - Đây là cách tiếp cận tốt nhất khi viết bài kiểm thử đa nền tảng.
- Ví dụ:
- Được sử dụng để tìm phần tử thông qua
-
XPath
- Xác định phần tử dựa trên cấu trúc XML. Đây là cách linh hoạt nhất nhưng cũng chậm nhất. Tuy nhiên cũng không chậm lắm đâu, cứ dùng thoải mái. Xpath hỗ trợ rất nhiều cú pháp tìm kiếm hay và gọn, cần nắm rõ các cú pháp thì mới dùng chuẩn xác hơn ổn định hơn.
- Ví dụ:
- Xác định phần tử dựa trên cấu trúc XML. Đây là cách linh hoạt nhất nhưng cũng chậm nhất. Tuy nhiên cũng không chậm lắm đâu, cứ dùng thoải mái. Xpath hỗ trợ rất nhiều cú pháp tìm kiếm hay và gọn, cần nắm rõ các cú pháp thì mới dùng chuẩn xác hơn ổn định hơn.
-
Class Name
- Tìm phần tử dựa trên tên lớp của nó (ví dụ:
android.widget.ImageView
hoặcXCUIElementTypeButton
). Cách này ít được dùng vì nó dễ bị trùng lặp nhiều element. - Ví dụ:
- Tìm phần tử dựa trên tên lớp của nó (ví dụ:
-
UIAutomator (Android)
- Sử dụng cú pháp của UIAutomator (framework của Android) để xác định phần tử. Chỉ hỗ trợ cho Android, nên ít được dùng khi test cả iOS.
- Ví dụ:
driver.findElement(AppiumBy.androidUIAutomator("new UiSelector().text(\"Sauce Labs Backpack\")"));
- Sử dụng cú pháp của UIAutomator (framework của Android) để xác định phần tử. Chỉ hỗ trợ cho Android, nên ít được dùng khi test cả iOS.
-
iOS Predicate String (iOS)
- Sử dụng câu truy vấn predicate để tìm phần tử trên iOS.
- Ví dụ:
driver.findElement(AppiumBy.iOSNsPredicateString("type == 'XCUIElementTypeButton' AND label == 'Submit'"));
Chọn locators như thế nào?
- Ưu tiên sử dụng
Accessibility ID
hoặcID
: Đây là cách nhanh nhất và đáng tin cậy nhất. - Sau đó dùng
XPath
: Mặc dù linh hoạt, nhưng nó chậm hơn so với các locators khác. - Luôn kiểm tra tính duy nhất của locator: Một locator nên xác định chính xác một phần tử duy nhất trên màn hình.
✅Xác định locators dựa vào XPATH axes (tương đối)
XPath axes là một khái niệm trong XPath (XML Path Language), được sử dụng để xác định mối quan hệ giữa các nút (nodes) trong tài liệu XML. Axes giúp bạn chọn các nút liên quan đến một nút hiện tại (current node) dựa trên vị trí và mối quan hệ của chúng trong cây XML.
Giả sử giao diện ứng dụng Android Mobile có cấu trúc XML như sau:
<android.widget.LinearLayout>
<android.widget.TextView text="Header" />
<android.widget.LinearLayout>
<android.widget.TextView text="Item 1" />
<android.widget.TextView text="Item 2" />
<android.widget.TextView text="Item 3" />
</android.widget.LinearLayout>
<android.widget.Button text="Submit" />
</android.widget.LinearLayout>
1. Chọn phần tử con trực tiếp (child::
)
Giả sử bạn muốn tìm tất cả các nút con của android.widget.LinearLayout
:
WebElement parentElement = driver.findElement(By.xpath("//android.widget.LinearLayout"));
List<WebElement> childElements = parentElement.findElements(By.xpath("child::*"));
for (WebElement element : childElements) {
System.out.println(element.getAttribute("text"));
}
2. Chọn phần tử tổ tiên (ancestor::
)
Tìm nút tổ tiên của phần tử Submit
:
WebElement submitButton = driver.findElement(By.xpath("//android.widget.Button[@text='Submit']"));
WebElement ancestorElement = submitButton.findElement(By.xpath("ancestor::android.widget.LinearLayout"));
System.out.println("Ancestor found: " + ancestorElement.getTagName());
Hoặc có thể viết liền nhau không cần tạo ra 2 đối tượng element, dùng dấu xẹt (/):
WebElement ancestorElement = submitButton.findElement(By.xpath("//android.widget.Button[@text='Submit']/ancestor::android.widget.LinearLayout"));
System.out.println("Ancestor found: " + ancestorElement.getTagName());
3. Chọn phần tử sau nó (following-sibling::
)
Tìm tất cả các nút anh chị em nằm sau Item 1
:
WebElement item1 = driver.findElement(By.xpath("//android.widget.TextView[@text='Item 1']"));
List<WebElement> followingSiblings = item1.findElements(By.xpath("following-sibling::android.widget.TextView"));
for (WebElement sibling : followingSiblings) {
System.out.println("Following sibling: " + sibling.getAttribute("text"));
}
4. Chọn phần tử trước nó (preceding-sibling::
)
Tìm tất cả các nút anh chị em nằm trước Item 3
:
WebElement item3 = driver.findElement(By.xpath("//android.widget.TextView[@text='Item 3']"));
List<WebElement> precedingSiblings = item3.findElements(By.xpath("preceding-sibling::android.widget.TextView"));
for (WebElement sibling : precedingSiblings) {
System.out.println("Preceding sibling: " + sibling.getAttribute("text"));
}
5. Chọn tất cả phần tử con hoặc chính nó (descendant-or-self::
)
Tìm tất cả các phần tử con (kể cả nút hiện tại) của nút android.widget.LinearLayout
:
WebElement layout = driver.findElement(By.xpath("//android.widget.LinearLayout"));
List<WebElement> descendants = layout.findElements(By.xpath("descendant-or-self::*"));
for (WebElement element : descendants) {
System.out.println("Descendant: " + element.getTagName());
}
6. Chọn thuộc tính của một phần tử (attribute::
)
Lấy giá trị của thuộc tính text
cho nút Submit
:
WebElement submitButton = driver.findElement(By.xpath("//android.widget.Button[@text='Submit']"));
String textValue = submitButton.getAttribute("text");
System.out.println("Button text: " + textValue);
7. Sử dụng XPath để tìm phần tử dựa trên text
Dùng cú pháp XPath để chọn phần tử dựa trên giá trị của thuộc tính text
. Đây là cách được sử dụng nhiều khi dùng đến cú pháp XPath.
Vì đôi khi các thuộc tính khác lại ít tồn tại sẵn trên giao diện, do anh bạn Developer không bỏ thuộc tính đầy đủ vào như id, accessibility id.
Ví dụ 1: Tìm nút có text="Submit"
WebElement submitButton = driver.findElement(By.xpath("//android.widget.Button[@text='Submit']"));
submitButton.click();
Ví dụ thực tế về text trên app mobile:
Ví dụ 2: Tìm tất cả các phần tử có text="Item 1"
Nếu muốn lấy danh sách các phần tử có cùng text
:
List<WebElement> items = driver.findElements(By.xpath("//android.widget.TextView[@text='Item 1']"));
for (WebElement item : items) {
System.out.println(item.getAttribute("text"));
}
8. Sử dụng contains()
để tìm phần tử chứa một phần của text
Khi text
không hoàn toàn khớp, bạn có thể sử dụng hàm contains()
trong XPath:
Ví dụ: Tìm phần tử có text
chứa từ "Item":
WebElement element = driver.findElement(By.xpath("//*[contains(@text, 'Item')]"));
System.out.println("Found element with text: " + element.getAttribute("text"));
9. Tìm phần tử với text
bất chấp chữ hoa/thường
Sử dụng hàm translate()
trong XPath để chuyển tất cả text
về chữ thường hoặc chữ hoa trước khi so sánh.
Ví dụ: Tìm phần tử có text="submit"
bất kể viết hoa/thường:
WebElement element = driver.findElement(By.xpath("//*[translate(@text, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')='submit']"));
element.click();
10. Kết hợp text
và các điều kiện khác
Bạn có thể kết hợp điều kiện text
với các thuộc tính khác, như class hoặc id:
Ví dụ: Tìm phần tử trong phần TextView
có text="Item 1"
và thuộc class cụ thể:
WebElement element = driver.findElement(By.xpath("//android.widget.TextView[@text='Item 1' and @class='android.widget.TextView']"));
System.out.println("Element found: " + element.getAttribute("text"));