1. Locator “sống lâu” là gì?

Dựa trên tài liệu và ngữ cảnh về kiểm thử tự động trên LLQ QA Platform, thuật ngữ "Locator sống lâu" (hay locator ổn định/stable locator) không được định nghĩa nguyên văn, nhưng được mô tả qua các nguyên tắc tạo và quản lý phần tử để tránh lỗi "Element not found". Một locator được coi là "sống lâu" khi nó đảm bảo các tiêu chí sau:

1.1 Được lưu trữ trong Element Repository (Thay vì Hardcode)

Một locator "sống lâu" là locator không gắn chết vào từng dòng code (hardcode). Nó phải được lưu trong Element Repository.

  • Lý do: Khi giao diện thay đổi, bạn chỉ cần cập nhật locator này trong kho một lần duy nhất. Sự "sống còn" của nó được duy trì trên hàng trăm Test Script đang tham chiếu tới nó mà không cần sửa đổi kịch bản.
1.2 Sử dụng chiến lược định danh bền vững

Locator "sống lâu" tránh sử dụng cấu trúc tuyệt đối hoặc các thuộc tính dễ thay đổi (như CSS class ngẫu nhiên). Thay vào đó, nó sử dụng:

  • Thuộc tính đặc trưng: Ưu tiên id, name hoặc kết hợp nhiều thuộc tính (ví dụ: tag + attribute) để đảm bảo tính duy nhất.
  • Cấu trúc tương đối: Sử dụng XPath tương đối hoặc quan hệ cha-con lỏng lẻo để không bị ảnh hưởng khi cấu trúc DOM thay đổi nhỏ.
1.3 Có khả năng thích nghi với dữ liệu động (Dynamic)

Locator dễ bị "chết" khi dữ liệu hiển thị thay đổi (ví dụ: số tiền, ngày tháng). Locator "sống lâu" xử lý vấn đề này bằng cách:

  • Sử dụng biến (Variable): Thay vì fix cứng giá trị (ví dụ: text='30,000 VND'), locator sử dụng biến (ví dụ: text='{menh_gia}').
  • Custom Element: Sử dụng tính năng Custom element để truyền giá trị động vào thuộc tính locator ngay tại thời điểm chạy (runtime), giúp locator hoạt động đúng với mọi dữ liệu đầu vào.
1.4 Được hỗ trợ bởi cơ chế "Healing" (Tự chữa lành)

Trên LLQ QA Platform, một locator có thể "sống lâu" hơn nhờ tính năng Update Healing trong Smart Locator.

  • Khi quét lại màn hình, nếu thuộc tính cũ bị sai, hệ thống sẽ tự động cập nhật lại thông tin mới nhất cho locator đó trong kho thay vì tạo mới hoặc để nó bị lỗi.

2 Thứ tự ưu tiên khi chọn locator

Thứ tự ưu tiên khi chọn locator (định vị phần tử) được khuyến nghị để đảm bảo tính ổn định và dễ bảo trì như sau:

2.1. Ưu tiên 1: Sử dụng Element Repository (Khuyên dùng nhất)

Đây là phương pháp được hệ thống khuyến khích sử dụng hàng đầu thay vì viết trực tiếp giá trị vào kịch bản.

  • Lý do: Khi thuộc tính của phần tử thay đổi, bạn chỉ cần cập nhật một lần trong kho lưu trữ (Repository). Tất cả các kịch bản kiểm thử (Test Script) sử dụng phần tử đó sẽ tự động cập nhật theo, giúp tránh lỗi và giảm công sức bảo trì.
  • Cách thực hiện: Trong cấu hình bước test, tại khối Locator, chọn kiểu dữ liệu là Repository Element và chọn phần tử đã lưu.
2.2. Ưu tiên 2: Sử dụng công cụ Find Element / Smart Locator

Nếu chưa có sẵn trong kho, hãy sử dụng các công cụ tự động của hệ thống để tìm và tạo locator chuẩn thay vì tự viết.

  • Smart Locator: Dùng để quét và tạo hàng loạt element dựa trên các Element Template đã định nghĩa sẵn. Cách này giúp chuẩn hóa locator theo quy tắc chung của dự án.
  • Find Element: Dùng để tìm nhanh element trực tiếp trên màn hình đang debug để thêm vào kịch bản. Hệ thống sẽ tự động sinh ra locator dựa trên template (Basic hoặc Advanced).
2.3. Ưu tiên 3: Viết XPath thủ công (Không khuyến nghị)

Đây là lựa chọn cuối cùng, hệ thống không khuyến nghị trừ những trường hợp đặc biệt.

  • Khi nào dùng: Chỉ nên dùng khi element có cấu trúc quá phức tạp, đặc biệt mà các template có sẵn không thể nhận diện được.
  • Cấu trúc chuẩn: Khi viết tay, cần tuân thủ cấu trúc: //Element[@tag attribute='value'].

Chiến lược chọn thuộc tính (Attribute Strategy)

Khi cấu hình locator (dù tự động hay thủ công), tài liệu đưa ra các nguyên tắc để đảm bảo độ chính xác:

  • Kết hợp thuộc tính: Nên cấu hình locator sử dụng từ hai thuộc tính trở lên trong công thức XPath để đảm bảo khả năng phân biệt chính xác giữa các phần tử, tránh việc hệ thống bắt nhầm phần tử khác.
  • Thuộc tính đặc trưng: Cần phân tích giao diện để xác định các thuộc tính đặc trưng (như ID, Name, hoặc Text duy nhất).
  • Xử lý phần tử động: Đối với các locator thay đổi theo dữ liệu đầu vào (ví dụ: chọn số tiền 30,000đ hay 50,000đ), không được fix cứng giá trị. Thay vào đó, hãy sử dụng tính năng Custom element hoặc New Variable để tạo xpath động.
    • VD: ...[@value='{biến_số_tiền}']

3 Tránh XPath tuyệt đối & XPath dài

Để tránh sử dụng XPath tuyệt đối và XPath quá dài, những nguyên nhân hàng đầu gây ra lỗi "Element not found" khi cấu trúc giao diện thay đổi, bạn cần áp dụng các chiến lược định danh dựa trên XPath tương đối và các công cụ hỗ trợ của LLQ QA Platform. 

Dưới đây là các phương pháp cụ thể:

3.1 Sử dụng Cấu trúc XPath Chuẩn (Relative XPath)

Thay vì mô tả toàn bộ đường dẫn từ gốc (ví dụ: /html/body/div/div/input...), tài liệu khuyến nghị sử dụng cấu trúc tương đối dựa trên các thuộc tính đặc trưng.

  • Cấu trúc khuyến nghị: //Element[@tag attribute='value'].
  • Nguyên tắc: Bắt đầu bằng // để tìm kiếm phần tử ở bất kỳ đâu trong tài liệu, sau đó thu hẹp phạm vi bằng tên thẻ (Tag) và thuộc tính (Attribute).
3.2 Chiến lược chọn thuộc tính (Attribute Strategy)

Để XPath ngắn gọn và ổn định, bạn cần chọn đúng thuộc tính định danh:

  • Ưu tiên thuộc tính duy nhất: Sử dụng các thuộc tính ít thay đổi và có tính định danh cao như id, name, label.
  • Kết hợp thuộc tính: Nếu một thuộc tính không đủ để xác định duy nhất (dễ bị trùng lặp), hãy kết hợp từ hai thuộc tính trở lên trong công thức XPath. Việc này giúp locator chính xác hơn mà không cần phải viết đường dẫn dài dòng dựa vào quan hệ cha-con.

Ví dụ: Thay vì //div/div/button, hãy dùng //button[@type='submit' and @name='login'].

3.3 Tận dụng Element Template để chuẩn hóa

Thay vì tự viết tay (dễ dẫn đến XPath dài hoặc không nhất quán), hãy sử dụng Element Template để hệ thống tự sinh XPath tối ưu.

  • Cấu hình công thức: Trong Template, bạn định nghĩa sẵn các công thức ngắn gọn (ví dụ: by_id chỉ lấy ID, by_text chỉ lấy Text).
  • Kết quả: Khi dùng Smart Locator quét màn hình, hệ thống sẽ ưu tiên sinh ra các XPath ngắn gọn theo công thức đã cấu hình thay vì sinh ra các XPath tuyệt đối dài dòng.
3.4 Xử lý phần tử có giá trị thay đổi (Dynamic XPath)

Một nguyên nhân khiến người dùng hay viết XPath dài hoặc sai là do cố gắng "bắt" các phần tử có nội dung thay đổi (ví dụ: nút chọn số tiền, tên người dùng).

  • Không hardcode giá trị: Tránh viết cứng giá trị vào XPath nếu giá trị đó thay đổi theo kịch bản.
  • Dùng biến (Variable): Hãy tạo XPath động bằng cách chèn tham số vào chuỗi XPath.
    • Ví dụ: //Element[@value='{ten_bien}'] thay vì //Element[@value='Giá trị cố định dài dòng'].
3.5 Lưu trữ trong Element Repository

Cuối cùng, ngay cả khi bạn có một XPath tốt, hãy luôn lưu nó vào Element Repository.

  • Việc này đảm bảo rằng nếu giao diện thay đổi cấu trúc khiến XPath (dù là tương đối) bị sai, bạn chỉ cần sửa tại một nơi duy nhất trong kho thay vì phải tìm và sửa trong hàng loạt file kịch bản.

4 Không phụ thuộc text dễ thay đổi

Để tránh phụ thuộc vào Text dễ thay đổi (ví dụ: ngôn ngữ thay đổi, nội dung động theo dữ liệu), bạn cần áp dụng các chiến lược định danh dựa trên các thuộc tính kỹ thuật bền vững (như ID, Name) hoặc sử dụng biến động thay vì giá trị cố định.

Dưới đây là các phương pháp cấu hình cụ thể trên LLQ QA Platform:

4.1 Cấu hình Element Template ưu tiên thuộc tính kỹ thuật

Thay vì để hệ thống tự động bắt theo Text, bạn cần cấu hình Element Template để ưu tiên các thuộc tính định danh duy nhất và ít thay đổi.

  • Cấu hình Result xpath list: Trong phần cấu hình Template, hãy tạo các công thức ưu tiên tìm kiếm theo id, name, resource-id (với Mobile) hoặc class kết hợp vị trí. 
    • Ví dụ: Thay vì dùng công thức by_text (tìm //button[text()='Đăng nhập']), hãy cấu hình công thức by_id để sinh ra //button[@id='login_btn'].
    • Hệ thống cho phép bạn định nghĩa thứ tự ưu tiên: Hãy đặt các công thức dựa trên ID hoặc Name lên đầu danh sách Result xpath list để Smart Locator ưu tiên sử dụng chúng trước.
4.2 Sử dụng "Contains" cho Text thay đổi một phần

Nếu bắt buộc phải dùng Text nhưng nội dung có phần biến động (ví dụ: "Welcome, User A" -> "Welcome, User B"), hãy sử dụng toán tử Contains trong cấu hình Template.

  • Cách làm: Trong phần Result xpath list, tại dòng cấu hình thuộc tính, thay vì chọn Type là Value (so sánh bằng tuyệt đối), hãy chọn Contains.
  • • Kết quả: XPath sinh ra sẽ có dạng //tag[contains(text(), 'Welcome')], giúp element vẫn hoạt động được khi tên người dùng thay đổi.
4.3 Xử lý Text động bằng Biến (Variable) và Custom Element

Đối với các trường hợp Text thay đổi hoàn toàn theo kịch bản (ví dụ: chọn mệnh giá tiền, chọn tên sản phẩm cụ thể), bạn tuyệt đối không hardcode giá trị text vào XPath.

  • Sử dụng Custom Element:
    • Khi cấu hình Template, hãy định nghĩa các thuộc tính như text là một tham số.
    • Khi viết kịch bản, sử dụng tính năng Custom element. Tại đây, bạn tick chọn thuộc tính text và truyền vào một biến (variable) thay vì một chuỗi ký tự cố định.
  • Tạo XPath động với New Variable:
    • Bạn có thể tạo một biến XPath động bằng cách ghép chuỗi: //Element[@text=' + {biến_text} + '].
    • Khi chạy kịch bản, hệ thống sẽ tự động điền giá trị text mong muốn vào XPath, giúp locator hoạt động linh hoạt với mọi ngôn ngữ hoặc dữ liệu đầu vào.
4.4 Kết hợp nhiều thuộc tính (Combine Attributes)

Nếu một thuộc tính không đủ (ví dụ Text thay đổi, ID bị trùng), hãy cấu hình Template để kết hợp nhiều thuộc tính nhằm đảm bảo tính duy nhất mà không phụ thuộc hoàn toàn vào Text.

  • Cấu hình: Trong Result xpath list của Template, bạn có thể thêm nhiều dòng Attribute (Add attribute) cho cùng một công thức.
  • Ví dụ: Kết hợp Class + Index hoặc Type + Name để định vị chính xác mà không cần dùng đến Text hiển thị trên giao diện

5 Ví dụ locator tốt vs xấu

Dưới đây là so sánh chi tiết giữa Locator Tốt (nên dùng) và Locator Xấu (nên tránh) để đảm bảo kịch bản kiểm thử hoạt động ổn định.

5.1 So sánh trực quan: Tốt vs Xấu

Tiêu chí

Locator xấu (Dễ lỗi, khó bảo trì)

Locator Tốt ( Ổn định, dễ bảo trì)

Cách lưu trữ

Hardcode trong Script, nhập trực tiếp XPath vào ô Value của keyword.

Ví dụ: //input[@id='user']

Repository Element, lưu trong kho và tham chiếu bằng tên.

Ví dụ: Login_page / txt_username

Giá trị động

Cố định giá trị (Hardcode value), tạo riêng từng element cho mỗi giá trị dữ liệu.

Ví dụ: //div[@text='30,000 VND']

Dùng biến số (Variable), một element xử lý được mọi dữ liệu.

Ví dụ: //div[@text='${menh_gia}']

Cấu trúc

XPath tuyệt đối / Quá dài, phụ thuộc chặt vào cấu trúc HTML.

Ví dụ: /html/body/div/div/input

XPath tương đối / Thuộc tính đặc trưng, dựa vào ID, Name hoặc thuộc tính duy nhất.

Ví dụ: //input[@id='username']

Độ chính xác

Chung chung / Thiếu chi tiết, dễ bắt nhầm phần tử khác.

Ví dụ: //input (bắt nhầm ô search thay vì login)

Kết hợp thuộc tính, kết hợp nhiều điều kiện để đảm bảo duy nhất.

Ví dụ: //input[@id='user' and @type='text']

Text hiển thị

So sánh bằng tuyệt đối (=), lỗi ngay khi text thay đổi nhỏ (thêm dấu cách, đổi từ).

Ví dụ: text()='Xin chào User'

So sánh tương đối (Contains), vẫn chạy đúng khi text thay đổi một phần.

Ví dụ: contains(text(), 'Xin chào')

5.2 Phân tích ví dụ thực tế

Ví dụ: Để lựa chọn mệnh giá, kịch bản kiểm thử cần thực hiện truyền dữ liệu mong muốn cho mỗi test case là 30,000 VND, 50,000 VND, …

Cách làm xấu:

  • Tạo 3 element riêng biệt trong kho: btn_30k, btn_50k, …
  • XPath của btn_30k: // XCUIElementTypeStaticText[@text='30,000 VND'].
  • Hậu quả: Nếu cần test 10 mệnh giá, bạn phải tạo 10 element. Khi giao diện đổi cấu trúc thẻ div sang span, bạn phải sửa 10 lần.

Cách làm tốt:

  • Tạo duy nhất 1 element đại diện cho nút chọn mệnh giá.
  • Sử dụng New Variable để tạo XPath động.

Cấu hình keyword New Variable:

Trong đó:

  • Step comment: Nhập ghi chú cho bước thao tác của keyword, giúp kịch bản kiểm thử được hiểu một cách rõ ràng hơn
  • Data Type: String
  • Name: Nhập tên của biến, đối với biến xpath “động”, nhân viên kiểm thử nên đặt tên liên quan đến phần tử được tương tác cùng với “xpath” để dễ dàng phân biệt các tham số chỉ vị trí và giá trị
  • isList: false
  • Variable init: false

Cấu thức XPath: //XCUIElementTypeStaticText[@value="menh_gia_nap_string"]

Khi đó ta có:

Lợi ích: Chỉ cần truyền giá trị "50,000" hoặc "100,000" vào biến menh_gia_nap_string khi chạy, hệ thống sẽ tự tìm đúng nút đó. Chỉ cần bảo trì 1 chỗ.

Sửa lần cuối: Thứ Ba, 24 tháng 2 2026, 9:39 AM