Việc xác định vị trí một phần tử trên trang web có thể là một thách thức, đặc biệt với các trang web được lập trình động như hiện nay. Do đó việc dùng các định vị như ID, Name, linkText … sẽ khó thực hiện được vì các phần tử không có giá trị thuộc tính nhất quán. Vậy chúng ta sẽ làm như thế nào đối với những trường hợp này?
Selenium Locator có hỗ trợ XPath và CSS Selector để sử dụng khi cần định vị các phần tử web không có ID, Name, …
Trong bài này, chúng ta sẽ cùng tìm hiểu về CSS Selector nhé!
CSS là gì?
CSS là viết tắt của Cascading Style Sheet. CSS cung cấp giao diện và bố cục cho một trang web. Cùng với HTML, nó giúp cho trang web trở nên đẹp hơn.
CSS Selector trong Selenium WebDriver
Về cơ bản, CSS Selector là cách kết hợp việc chọn một phần tử (element) và giá trị (value) mà có thể xác định được các phần tử cụ thể trên trang web. Sự kết hợp này được gọi là Selector Pattern. Selector Pattern được xây dựng bằng cách sử dung các thẻ HTML, thuộc tính (attributes), và giá trị (value) của chúng.
Lợi ích khi sử dụng CSS Selector
- Dễ đọc hơn, ngắn gọn và chính xác hơn.
- Nhanh hơn XPath, đặc biệt trong trường hợp chạy trên trình duyệt IE.
- Là loại định vị được ưa thích và sử dụng rộng rãi.
Hạn chế của CSS Selector
- Các trình duyệt cũ không hỗ trợ, như là IE8
- Khi sử dụng CSS Selector, một phần tử có thể được tìm thấy bằng cách quét từ trên xuống
- Viết các CSS Selector phức tạp rất khó
Chúng ta sẽ tìm hiểu tuần tự từ dễ đến khó nhé.
1. Sử dụng ID
Trong hầu hết các trường hợp thì ID là cách lý tưởng nhất dùng để định vị element nếu nó có sẵn. Nó được viết bằng cách đặt ký hiệu “#” trước thuộc tính ID. Bạn cần lưu ý các ID là duy nhất trên trang và giữ nguyên trạng thái tĩnh khi tải trang.
Cấu trúc:
By.cssSelector("#ID")
Ví dụ: HTML <button id="firstButton" type="button" name="buttonSubmit">Submit</button>
CSS Selector: findElement(By.cssSelector("#firstButton"))
Cách sử dụng By.ID: findElement(By.ID("firstButton"))
Chúng ta cũng có thể kết hợp thẻ Tag với ID để xác đinh cho rõ hơn như sau
Cấu trúc: By.cssSelector("tag#id")
Ví dụ: findElement(By.cssSelector("button#firstButton"))
2. Sử dụng Class
Cũng giống với ID, nhưng nó được viết bằng cách đặt ký hiệu “.” trước thuộc tính class.
Cấu trúc: By.cssSelector(".class")
Ví dụ findElement(By.cssSelector(".btn")
Cách sử dụng By.class: findElement(By.className("btn"))
Hoặc chúng ta sử dụng CSS selector bằng cách kết hợp thẻ Tag và class như sau:
Cấu trúc: By.cssSelector("tag.class")
Ví dụ: findElement(By.cssSelector("button.btn"))
3. Sử dụng thuộc tính (Attributes)
Về cơ bản thì một attribute được xem là tính chất của một element. Và một Element thì có nhiều tính chất khác nhau. Ví dụ bên dưới thì ta có các thuộc tính như “name”, “class”, “placeholder”, “type”
<input id="name" name="enter-name" placeholder="Enter Your Name" type="text">
Có nhiều cách định vị element sử dụng với Attribute như sau
Sử dụng một attribute
Cấu trúc: findElement(By.cssSelector(["name='buttonSubmit']"))
Ví dụ: findElement(By.cssSelector(["name='buttonSubmit']"))
Sử dụng nhiều attributes
Cấu trúc: By.cssSelector("[attribute_name1='attribute_value1'][attribute_name2='attribute_value2']")
Ví dụ: findElement(By.cssSelector("[name='buttonSubmit'][type='button']"))
Sử dụng Tag và Attribute
- Một attribute
Cấu trúc: By.cssSelector("tag[attribute_name='attribute_value']")
Ví dụ: findElement(By.cssSelector("button[name='buttonSubmit']"))
- Nhiều attributes
Cấu trúc: By.cssSelector("tag[attribute_name1='attribute_value1'][attribute_name2='attribute_value2']")
Ví dụ: findElement(By.cssSelector("button[name='buttonSubmit'][type='button']"))
Sử dụng Tag, Class và Attribute
Cấu trúc: By.cssSelector("tag.class[attribute_name='attribute_value']")
Ví dụ: findElement(By.cssSelector("button.btn[name='buttonSubmit']"))
4. Sử dụng inner text
Chúng ta cũng có thể sử dụng nội dung của các element để định vị nó.
Cấu trúc: By.cssSelector("tag:contains('inner text')")
Ví dụ: findElement(By.cssSelector("button:contains('submit')")
5. Sử dụng wild card
Trong thực tế khi làm việc với selenium, không phải lúc nào cũng có sẵn ID duy nhất và ID tĩnh cho bạn dùng, mà thay vào đó là ID được dev sử dụng cho các elements khác nhau hay là ID động (là loại ID sẽ thay đổi sau mỗi lần trang web được load lại).
Ví dụ: Load lần 1: <button id="submit_btn_363" type="button">Submit</button>
Load lần 2: <button id="submit_btn_364" type="button">Submit</button>
Vậy chúng ta sẽ xử lý thế nào đây?
CSS Selector có cung cấp tính năng wild card, là cách mà chúng ta có thể sử dụng để làm những việc nâng cao hơn như chỉ khớp với một phần của thuộc tính. Dưới đây là 3 loại được sử dụng nhiều nhất
“^=” Start with
Matching với phần đầu của thuộc tính. Sử dụng ký hiệu “^=”
Cấu trúc: By.cssSelector("tag(attribute_name^='attribute_value')")
Ví dụ: findElement(By.cssSelector("button(id^='submit')")
“$=” End with
Matching với phần cuối của thuộc tính. Sử dụng ký hiệu “$=”
Cấu trúc: By.cssSelector("tag(attribute_name^='attribute_value')")
Ví dụ: findElement(By.cssSelector("button(id$='btn_363')")
“*=” Contains
Matching với bất kỳ vị trí nào của thuộc tính. Sử dụng ký hiệu “*=”
Cấu trúc: By.cssSelector("tag(attribute_name*='attribute_value')")
Ví dụ: findElement(By.cssSelector("button(id*='btn')")
6. Direct Child
Các trang HTML có cấu trúc giống như XML, với các trang con được lồng vào bên trong của các trang cha.
Cấu trúc: By.cssSelector("tag_name(attribute_name='attribute_value')>tag_name(attribute_name='attribute_value')")
Ví dụ:
CSS Selector findElement(By.cssSelector("div>a")
Xpath: findElement(By.xpath("//div/a")
7. Child or Sub-Child
Nếu một phần tử nằm bên trong một phần tử khác hoặc một phần tử con của chính nó, như việc lồng các div với nhau, thì việc xác định phần tử đó trong XPATH chúng ta sẽ sử dụng ký hiệu “//”, trong khi CSS chỉ bằng một khoảng trắng
Cấu trúc: By.cssSelector("tag_name(attribute_name='attribute_value') tag_name(attribute_name='attribute_value')")
Ví dụ: CSS Selector findElement(By.cssSelector("div a")
Xpath: findElement(By.xpath("//div//a")