NỘI DUNG BÀI HỌC
1. Làm việc với Checkbox
Trong các ứng dụng web, checkbox là một trong những element bạn sẽ thường gặp rất là nhiều. Vậy thì làm thế nào để test checkbox này với Selenium?
Một cách trực quan, nếu nhìn bằng mắt thường thì ta có thể nhận biết ngay lập tức màn hình chức năng này có checkbox hay không, checkbox nào đã được check hay chưa được check. Tuy nhiên, làm thế nào để Selenium làm được điều này, chúng ta cùng tìm hiểu bài toán và tìm ra lời giải dưới đây nhé.
Hình dáng Checkbox trên web:
Link Demo: https://crm.anhtester.com/admin/authentication
admin@example.com
123456
Checkbox có nhãn là Public:
Checkbox có nhãn là Billable:
Để biết được element này có phải là checkbox hay không, ta sẽ dựa vào thuộc tính trong thẻ HTML của phần tử đó, ở ví dụ trên ta có thể quan sát thấy các checkbox đều có type = "checkbox".
🔆 Xử lý checkbox với automation:
Đầu tiên để tích chọn vào ô checkbox thì ta dùng hàm click() bình thường vào chính ô input hoặc label gắn liền với checkbox nếu có.
Ví dụ click chọn checkbox Public:
driver.findElement(By.xpath("//input[@id='task_is_public']")).click();
//hoặc
driver.findElement(By.xpath("//label[normalize-space()='Public']")).click();
🔆 Đặc trưng bản chất của Checkbox là được tích chọn nhiều giá trị checkbox trong một danh sách các checkbox. Nó khác với Radio button ở phần sau.
Tiếp theo nếu muốn kiểm tra xem checkbox này đã được check hay chưa, hay kiểm tra checkbox này có giá trị default đã đúng chưa thì chúng ta sử dụng hàm isSelected() trong Selenium để kiểm tra.
Nếu như checkbox đó đã được check, kết quả trả về là true, và ngược lại chưa được check thì kết quả trả về là false.
Lưu ý là chúng ta phải lấy locator đến chính cái thẻ input thì mới kiểm tra được nhé, vì thẻ input mới chứa type="checkbox". Còn cái label hoặc các thẻ html khác đi kèm thì chỉ để click chọn thôi chứ không phải để kiểm tra.
Ví dụ kiểm tra checkbox Public:
driver.findElement(By.xpath("//input[@id='task_is_public']")).isSelected();
Ví dụ chúng ta kiểm tra nếu như checkbox chưa được check thì thực hiện click vào ô checkbox đó:
//Kiểm tra checkbox đã được check hay chưa
boolean isSelected = driver.findElement(By.xpath("//input[@id='task_is_public']")).isSelected();
//Nếu chưa được check thì click vào ô check box đó
if(isSelected == false)
{
driver.findElement(By.xpath("//input[@id='task_is_public']")).click();
}
Có thể thực hiện với trường hợp ngược lại là nếu checkbox đã được check thì thực hiện bỏ check cho check box, trường hợp này về bản chất thì không khác so với trường hợp true, vì với checkbox thì ta click lần 1 là check, click tiếp lần 2 thì là bỏ check, do đó ta cũng sẽ làm tương tự đối với trường hợp false này.
🔆Code demo xử lý Radio button với Selenium Java:
package com.anhtester.Bai8_Checkbox_Radio_Dropdown;
import com.anhtester.Bai5_LocatorElement.LocatorsCRM;
import com.anhtester.common.BaseTest;
import org.openqa.selenium.By;
public class DemoCheckbox extends BaseTest {
public static void main(String[] args) throws InterruptedException {
createDriver();
loginCRM();
driver.findElement(By.xpath(LocatorsCRM.menuTasks)).click();
driver.findElement(By.xpath(LocatorsCRM.buttonNewTask)).click();
Thread.sleep(2000);
//Click chọn checkbox Public
driver.findElement(By.xpath("//input[@id='task_is_public']")).click();
//driver.findElement(By.xpath("//label[normalize-space()='Public']")).click();
//Kiểm tra checkbox đã được check hay chưa
//driver.findElement(By.xpath("//input[@id='task_is_public']")).isSelected();
boolean isSelected = driver.findElement(By.xpath("//input[@id='task_is_billable']")).isSelected();
System.out.println("isSelected: " + isSelected);
//Nếu chưa được check thì click vào ô check box đó
if (isSelected == false) {
System.out.println("Click chọn checkbox Public");
driver.findElement(By.xpath("//input[@id='task_is_billable']")).click();
}
Thread.sleep(2000);
closeDriver();
}
}
Các hàm createDriver() closeDriver() và loginCRM() được khai báo bên class BaseTest:
package com.anhtester.common;
import com.anhtester.Bai5_LocatorElement.LocatorsCRM;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.time.Duration;
public class BaseTest {
public static WebDriver driver;
public static void createDriver() {
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
}
public static void closeDriver() {
driver.quit();
}
public static void loginCRM(){
driver.get("https://crm.anhtester.com/admin/authentication");
driver.findElement(By.xpath(LocatorsCRM.inputEmail)).clear();
driver.findElement(By.xpath(LocatorsCRM.inputPassword)).clear();
driver.findElement(By.xpath(LocatorsCRM.inputEmail)).sendKeys("admin@example.com");
driver.findElement(By.xpath(LocatorsCRM.inputPassword)).sendKeys("123456");
driver.findElement(By.xpath(LocatorsCRM.buttonLogin)).click();
}
}
Với trường hợp có nhiều ô checkbox và ta muốn check nhiều hơn 1 trong số đó hoặc check hết thì cần kiểm tra và thêm thao tác click vào ô checkbox tiếp theo muốn check.
XỬ LÝ MULTIPLE CHECKBOX
🔆Cách thức xử lý automation cho Multiple Checkbox nào đó:
- Đầu tiên phải lấy ra được List<WebElement> danh sách các checkbox, dùng hàm driver.findElements()
Ví dụ: //div[@id='dashboard-options']//input[@type='checkbox']
=> Lấy tổng số Checkbox dùng hàm size() từ List
List<WebElement> listCheckbox = driver.findElements(By.xpath("//div[@id='dashboard-options']//input[@type='checkbox']"));
System.out.println("Tổng số checkbox: " + listCheckbox.size());
- Tiếp theo xử lý từng checkbox con bên trong:
+ Cách 1: Duyệt từng item trong List trên => Lấy ra được từng dòng chứa checkbox đólistCheckbox.get(i)
Duyệt vòng lặp for i chạy từ 0 đến < listCheckbox.size()
//Duyệt từng checkbox trong list element
for (int i = 0; i < listCheckbox.size(); i++) {
System.out.println("Checkbox thứ " + (i + 1) + ": " + listCheckbox.get(i).isSelected());
}
+ Cách 2: Dựa vào tổng số item và vị trí index từng item của locator trên để lấy ra đường dẫn tới chính xác element cần xử lý (input, label)
Duyệt vòng lặp for i chạy từ 1 đến <= listCheckbox.size() để truyền vào Xpath của Element chứa index đi kèm chính xác từng cái
Ví dụ:
//div[@id='dashboard-options']//input[@type='checkbox'] - là tổng số ô checkbox
(//div[@id='dashboard-options']//input[@type='checkbox'])[1] - là checkbox thứ nhất
(//div[@id='dashboard-options']//input[@type='checkbox'])[2] - là checkbox thứ hai
...
Thì khi đó chỉ cần thay thế các con số thành biến i để vòng lặp for tự chạy qua từng cái.
for (int i = 1; i <= listCheckbox.size(); i++) {
WebElement checkbox = driver.findElement(By.xpath("(//div[@id='dashboard-options']//input[@type='checkbox'])[" + i + "]"));
System.out.println("Checkbox thứ " + i + ": " + checkbox.isSelected());
}
🔆Code demo xử lý Multiple Checkbox với Selenium Java:
package com.anhtester.Bai8_Checkbox_Radio_Dropdown;
import com.anhtester.Bai5_LocatorElement.LocatorsCRM;
import com.anhtester.common.BaseTest;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import java.util.List;
public class DemoMultipleCheckbox extends BaseTest {
public static void main(String[] args) throws InterruptedException {
createDriver();
loginCRM();
driver.findElement(By.xpath("//div[@class='screen-options-btn']")).click();
Thread.sleep(2000);
//Danh sách các checkbox
List<WebElement> listCheckbox = driver.findElements(By.xpath("//div[@id='dashboard-options']//input[@type='checkbox']"));
System.out.println("Tổng số checkbox: " + listCheckbox.size());
//Duyệt từng checkbox trong list element
for (int i = 0; i < listCheckbox.size(); i++) {
System.out.println("Checkbox thứ " + (i + 1) + ": " + listCheckbox.get(i).isSelected());
}
//CÁCH XỬ LÝ THỨ HAI DÙNG XPATH INDEX
System.out.println("==============================");
for (int i = 1; i <= listCheckbox.size(); i++) {
WebElement checkbox = driver.findElement(By.xpath("(//div[@id='dashboard-options']//input[@type='checkbox'])[" + i + "]"));
System.out.println("Checkbox thứ " + i + ": " + checkbox.isSelected());
}
Thread.sleep(1000);
closeDriver();
}
}
2. Làm việc với Radio button
Cũng tương tự như checkbox, radio button cũng là một trong những element ta thường hay gặp trong các ứng dụng web.
Hình dáng Radio button trên web:
Link Demo: https://crm.anhtester.com/admin/authentication
admin@example.com
123456
🔆 Đặc trưng của Radio button là trong một nhóm các radio button thì tại một thời điểm ta chỉ có thể chọn một giá trị radio button trong các option tuỳ chọn đó. Trong HTML, các radio button nằm trong thẻ input và có thuộc tính là type = "radio".
Và ta có một vài vấn đề có thể làm với radio button như sau:
- Xác định locator của các radio button – có thể sử dụng nhiều cách để lấy ra được locator của các element này.
- Kiểm tra giá trị mặc định của radio, hoặc kiểm tra xem radio đó đã được chọn hay chưa
- Có thể click chọn nếu như radio button này chưa được chọn, hoặc chọn một radio khác khi radio kia đã được chọn
- Ngoài ra, trước khi click chọn radio button, ta có thể kiểm tra xem radio button đó có enable hay không – Case này được dùng trong trường hợp đối với một vài yêu cầu sau khi đã thực hiện một vài thao tác trước đó thì mới xuất hiện radio.
Đầu tiên, xác định locator của radio button:
driver.findElement(By.xpath("//input[@id='2']"));
Tiếp theo, kiểm tra giá trị mặc định của radio button là đã được check hay chưa bằng cách sử dụng hàm isSelected() - Hàm này cũng được dùng để kiểm tra với các Checkbox phía trên rồi đó.
driver.findElement(By.xpath("//input[@id='2']")).isSelected();
Kế tiếp nữa, là thực hiện click chọn radio button đó bằng cách sử dụng hàm click(), với locator đã tìm được ở bước đầu tiên:
driver.findElement(By.xpath("//input[@id='2']")).click();
//hoặc
driver.findElement(By.xpath("//label[normalize-space()='Hours']")).click();
Với trường hợp kiểm tra xem radio button có thể select được (enable and clickable) trên ứng dụng hay không ta có thể sử dụng hàm .isEnabled() để kiểm tra.
driver.findElement(By.xpath("//input[@id='1']")).isEnabled()
Ngoài ra còn có thể sử dụng hàm isDisplayed() để kiểm tra phần tử ấy có đang hiển thị hay không:
driver.findElement(By.xpath("//input[@id='1']")).isDisplayed()
🔆Code demo xử lý Radio button với Selenium Java:
package com.anhtester.Bai8_Checkbox_Radio_Dropdown;
import com.anhtester.Bai5_LocatorElement.LocatorsCRM;
import com.anhtester.common.BaseTest;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebElement;
public class DemoRadioButton extends BaseTest {
public static void main(String[] args) throws InterruptedException {
createDriver();
loginCRM();
driver.findElement(By.xpath(LocatorsCRM.menuSales)).click();
Thread.sleep(1000);
driver.findElement(By.xpath(LocatorsCRM.menuProposals)).click();
Thread.sleep(1000);
driver.findElement(By.xpath(LocatorsCRM.buttonNewProposal)).click();
Thread.sleep(2000);
//Scroll đến element
WebElement element = driver.findElement(By.xpath("//input[@id='2']"));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].scrollIntoView(true);", element);
Thread.sleep(1000);
//driver.findElement(By.xpath("//input[@id='2']")).click();
driver.findElement(By.xpath("//label[normalize-space()='Hours']")).click();
Thread.sleep(1000);
//Kiểm tra radio button đã được check hay chưa
boolean isSelected = driver.findElement(By.xpath("//input[@id='1']")).isSelected();
System.out.println("isSelected: " + isSelected);
//Nếu chưa được check thì click vào nút radio button đó
if (isSelected == false) {
driver.findElement(By.xpath("//input[@id='1']")).click();
}
Thread.sleep(2000);
closeDriver();
}
}
3. Làm việc với Dropdown List
3.1. Dropdown List tĩnh (dạng cũ hồi xưa)
Link Demo:
Yêu cầu:
- Làm sao để chọn các giá trị option của dropdown ở hình trên?
- Làm sao để kiểm tra trong dropdown có bao nhiêu giá trị? => như hình trên có 10 giá trị
- Làm sao để kiểm tra 1 giá trị trong dropdown hiển thị đúng hay chưa sau khi đã chọn thành công?
- Làm sao để kiểm tra dropdown có phải là multi-select hay single select (multi-select: cho phép chọn nhiều giá trị trong dropdown/ list)
Giải pháp:
- Selenium WebDriver hỗ trợ kiểm tra các phần tử Dropdown/ List bằng cách sử dụng lớp Select thay vì sử dụng lớp WebElement
import org.openqa.selenium.support.ui.Select;
- Lớp Select cung cấp các phương pháp và thuộc tính khác nhau để tương tác với dropdown/ list qua phần tử HTML là thẻ Select
Các phương thức sử dụng:
- Select dropdown sử dụng thuộc tính ID:
HTML:<select id="oldSelectMenu">
Select select = new Select(driver.findElement(By.id("oldSelectMenu")));
HTML:
- <option value="red">Red</option>
- <option value="1">Blue</option>
- ...
Select một giá trị trong dropdown sử dụng visible text (thường sử dụng)
select.selectByVisibleText("Red");
Select một giá trị trong dropdown sử dụng value
select.selectByValue("red");
Select một giá trị trong dropdown sử dụng index (bắt đầu từ vị trí số 0)
select.selectByIndex(3);
Kiểm tra dropdown có hỗ trợ dạng multi-select hay không:
select.isMultiple();
Lấy tổng số Option trong Select:
select.getOptions().size();
=> Mỗi 1 giá trị tương ứng với 1 thẻ <option>Lấy giá trị của dropdown hiển thị sau khi đã chọn thành công (giá trị đã chọn sẽ luôn hiển thị ở vị trí đầu tiên):
select.getFirstSelectedOption().getText();
🔆Code demo xử lý Dropdown List tĩnh với Selenium Java:
package com.anhtester.Bai8_Checkbox_Radio_Dropdown;
import com.anhtester.Bai5_LocatorElement.LocatorsCRM;
import com.anhtester.common.BaseTest;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
public class DemoDropdownStatic extends BaseTest {
public static void main(String[] args) throws InterruptedException {
createDriver();
driver.get("https://demoqa.com/select-menu");
Thread.sleep(2000);
//Scroll đến element
WebElement element = driver.findElement(By.xpath("//h1[normalize-space()='Select Menu']"));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].scrollIntoView(true);", element);
//Tạo class Select từ Selenium
Select select = new Select(driver.findElement(By.id("oldSelectMenu")));
Thread.sleep(2000);
//Select option theo text hiển thị
select.selectByVisibleText("Blue");
Thread.sleep(1000);
//Get giá trị sau khi đã chọn
System.out.println(select.getFirstSelectedOption().getText());
Thread.sleep(1000);
closeDriver();
}
}
3.2. Dropdown List động
Phần trước với các kiểu dropdown list và các method dùng trong việc xử lý các dropdown list tĩnh. Phần này sẽ xử lý với dropdown list động (Dynamic drop down list), để các bạn có thể dễ dàng làm việc với tất cả các loại dropdown khi xử lý trong automation test.
Bắt đầu, mình sẽ lấy một ví dụ về một dropdown động để hiểu hơn về yêu cầu của bài toán cũng như hướng giải quyết nhé.
Link Demo: https://techydevs.com/demos/themes/html/listhub-demo/listhub/index.html
Dưới đây là một trang web về đặt vé máy bay, người dùng sẽ click vào ô textbox điểm khởi hành để nhập vào điểm khởi hành chuyến bay. Khi click vào đó, trang web hiển thị ra danh sách các điểm khởi hành được gợi ý, người dùng có thể chọn từ list đó hoặc nhập vào các từ khóa, hệ thống sẽ hiển thị tên gợi ý tương ứng gần đúng với từ khóa nhập vào nhất.
Trong trường hợp này, ta không thể sử dụng cách thông thường sử dụng xử lý dropdown list tĩnh được, mà phải sử dụng bằng cách khác, cách này được mô tả theo kịch bản dưới đây:
Bước 1. Truy cập trang web
Bước 2. Click vào trường Category
Bước 3. Search từ khóa cần tìm
Bước 4. Click chọn category hiển thị trong dropdown phía dưới (hoặc dùng phím ENTER)
Kết quả mong muốn là Category đã chọn được hiển thị vào ô textbox trong dropdown.
🔆Code demo xử lý Dropdown List động với Selenium Java:
package com.anhtester.Bai8_Checkbox_Radio_Dropdown;
import com.anhtester.common.BaseTest;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.interactions.Actions;
public class DemoDropdownListDynamic extends BaseTest {
public static void main(String[] args) throws InterruptedException {
createDriver();
driver.get("https://techydevs.com/demos/themes/html/listhub-demo/listhub/index.html");
Thread.sleep(3000);
//Click vào dropdown Category
driver.findElement(By.xpath("//span[normalize-space()='Select a Category']")).click();
//Search giá trị cần chọn
Thread.sleep(1000);
driver.findElement(By.xpath("//span[normalize-space()='Select a Category']/parent::a/following-sibling::div//input")).sendKeys("Travel");
//Click chọn Text đã search (cần chọn)
Thread.sleep(1000);
driver.findElement(By.xpath("//li[@class='active-result highlighted']")).click();
//Cách ENTER dùng cho trường hợp chỉ hiển thị 1 giá trị lựa chọn
//Actions action = new Actions(driver);
//action.sendKeys(Keys.ENTER).perform();
Thread.sleep(2000);
closeDriver();
}
}
✳️ Cách debugger để xác định element khi nó không đứng yên để lấy
Dán mã này vào chỗ tab Console của DevTools, sau đó nó sẽ đứng yên cái trang web lại sau khoảng thời gian mình set cho chúng ta bắt locators của element. (ví dụ bên dưới 3000 là 3 giây)
setTimeout(()=>{debugger;}, 3000)
Bản chất là nó sẽ dừng cái Javascript trên trang web lại, nên cái phần tử web sẽ ở trạng thái đứng yên không tự bị ẩn đi.
Tiếp theo dùng cái dấu mũi tên lấy xpath như bình thường. Có thể kết hợp với tools SelectosHub để kiểm tra xpath cũng được.