Selenium là một trong những công cụ kiểm tra tự động hóa được sử dụng rộng rãi trên thị trường hiện nay, được sử dụng để kiểm tra các ứng dụng web. Selenium lần đầu tiên có mặt trên thị trường vào năm 2004 dưới dạng Selenium Core. Sau đó nó có một số phiên bản mở rộng cho nhiều loại như Selenium IDE, Selenium Webdriver, Selenium Grid và Selenium RC.
Cái mà Anh Tester muốn giới thiệu đến các bạn là Selenium WebDriver. Bản này nó cho phép chúngg ta viết code phát triển cùng với nhiều loại ngôn ngữ lập trình để chạy auto test cho website.
Theo Simon Stewart, Trưởng dự án của Selenium, giao thức W3C WebDriver là lý do để nâng cấp lên Selenium 4. Nó khác với giao thức JSON Wire ban đầu. Một trong những lợi thế liên quan đến thử nghiệm của chúng ta chạy nhất quán giữa các trình duyệt. Việc chuẩn hóa W3C tăng cường khả năng tương thích trên các triển khai API WebDriver phần mềm khác nhau.
W3C viết tắt của cụm từ World Wide Web Consutirum, W3C là chuẩn được các nhà thiết kế website sử dụng làm thước đo khi thiết kế các website. Chủ tịch của tổ chức đưa ra chuẩn này cũng là người đã sáng tạo ra giao thức HTTP và ngôn ngữ đánh dấu siêu văn bản HTML mà chúng ta sử dụng hiện nay.
Cho thấy ngày nay chuẩn W3C sẽ là chuẩn hiện đại chung, còn JSON Wire là chuẩn cũ nên Selenium đã tiến hành cải tiến để sau này dễ thích ứng và phát triển phù hợp cho nhiều nền tảng.
Sau khi Giao thức W3C được thay thế cho giao thức JSON Wire, bạn không cần mã hóa và giải mã các yêu cầu. Giao tiếp trực tiếp này mang lại sự ổn định và nhất quán hơn.
Để sử dụng Selenium mới nhất bạn có thể vào trang chủ docs của Selenium hoặc thông qua trang Maven hay Gradle.
Trang chủ Selenium HQ: https://www.selenium.dev/downloads/
Trang tải Selenium 4 từ Maven và Gradle: https://mvnrepository.com/search?q=Selenium
1) Phương thức tìm phần tử: Các phương thức tiện ích để tìm (các) phần tử trong giao diện "FindBy"
đã bị xóa vì chúng chỉ được sử dụng trong nội bộ. Thay vì điều này, lớp "By"
được chú thích để tăng tính ổn định.
Old:
driver.findElementByClassName("className");
New:
driver.findElement(By.className("className"));
2) Desired Capabilities
Old:
DesiredCapabilities caps = DesiredCapabilities.firefox();
caps.setCapability("platform", "Windows 10");
caps.setCapability("version", "104");
caps.setCapability("build", myTestBuild);
caps.setCapability("name", myTestName);
WebDriver driver = new RemoteWebDriver(new URL(cloudUrl), caps);
New:
FirefoxOptions browserOptions = new FirefoxOptions();
browserOptions.setPlatformName("Windows 10");
browserOptions.setBrowserVersion("104");
Map cloudOptions = new HashMap<>();
cloudOptions.put("build", myTestBuild);
cloudOptions.put("name", myTestName);
browserOptions.setCapability("cloud:options", cloudOptions);
WebDriver driver = new RemoteWebDriver(new URL(cloudUrl), browserOptions);
3) Actions class
Old:
moveToElement(WebElement).click()
moveToElement(WebElement).clickAndHold()
moveToElement(WebElement).contextClick()
moveToElement(WebElement).doubleClick()
New:
click(WebElement);
clickAndHold(WebElement);
contextClick(WebElement);
doubleClick(WebElement);
release()
: phương thức này (người dùng thả nút chuột đã nhấn) ban đầu là một phần của lớp org.openqa.selenium.interaction.ButtonReleaseAction
Bây giờ với phiên bản cập nhật của Selenium 4 thì nó đã được chuyển sang lớp Actions
.
4) Timeout Parameters: thay đổi kiểu đơn vị thời gian trong các hàm Wait của Selenium
Old:
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
WebDriverWait wait = new WebDriverWait(driver,10);
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
New:
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
driver.manage().timeouts().scriptTimeout(Duration.ofMinutes(2));
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(10));
WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(10));
Wait<WebDriver> fluentWait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofSeconds(5))
.ignoring(NoSuchElementException.class);
5) Browser Interface: Xoá bỏ hỗ trợ cho trình duyệt Opera và PhantomJS
Hiện tại chỉ còn hỗ trợ như sau:
Mà thằng IE cũng bị Microsoft khai tử luôn rồi nên có cũng như không hehe
Xem thêm Changes Log này: https://www.selenium.dev/selenium/docs/api/javascript/page/Changes.html
Anh Tester mới cập nhật tại phiên bản mới nhất hiện tại là v4.6.0 (updated 05/11/2022).
1) Chụp ảnh màn hình của phần tử web cụ thể: Trước đó trong Selenium 3 người dùng có thể chụp ảnh màn hình của toàn trang nhưng Selenium 4 đi kèm với một tính năng mới cho phép người dùng có thể chụp ảnh màn hình của một phần tử web cụ thể.
@Test
public void TC1_ScreenshotElement() {
driver.get("https://anhtester.com");
WebElement logo = driver.findElement(By.xpath("//a[@class='logo']"));
File file = logo.getScreenshotAs(OutputType.FILE);
File destFile = new File("logo.png");
try {
Files.copy(file.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
2) Mở tab mới trong trình duyệt: Trong Selenium 4 chúng ta có thể mở một tab mới trong trình duyệt cùng với tab hiện có với hàm hỗ trợ sẵn.
Chú ý: import class WindowType vào nhé !!
@Test
public void TC2_NewTab() {
driver.get("https://anhtester.com");
driver.switchTo().newWindow(WindowType.TAB);
driver.get("https://google.com");
}
3) Mở cửa sổ mới trong trình duyệt: Trong Selenium 4 chúng ta có thể mở một cửa sổ mới trong chính trình duyệt hiện tại.
@Test
public void TC3_NewWindow() {
driver.get("https://anhtester.com");
driver.switchTo().newWindow(WindowType.WINDOW);
driver.get("https://google.com");
}
4) Vị trí đối tượng: bây giờ sử dụng Selenium 4 người dùng có thể lấy được vị trí chính xác của các phần tử web như tọa độ, kích thước, chiều cao, chiều rộng, v.v. làm vị trí của đối tượng.
@Test
public void TC4_ObjectLocation() {
driver.get("https://anhtester.com");
WebElement element = driver.findElement(By.xpath("//a[@id='btn-login']"));
System.out.println("Height is: " + element.getRect().getDimension().getHeight());
System.out.println("Width is: " + element.getRect().getDimension().getWidth());
System.out.println("X location: " + element.getRect().getX());
System.out.println("Y location: " + element.getRect().getY());
}
5) Bộ định vị tương đối: Bộ định vị tương đối với chức năng mới được thêm vào để tìm ra phần tử trên một trang gần phần tử kia, hay nói cách khác là chúng ta có thể tìm một Web Element trên một trang web một cách tương đối.
@Test
public void TC5_RelativeLocators() throws InterruptedException {
driver.get("https://rise.fairsketch.com/signin");
WebElement password = driver.findElement(By.id("password"));
WebElement email = driver.findElement(RelativeLocator.with(By.tagName("input")).above(password));
email.clear();
email.sendKeys("anhtester@mailinator.com");
Thread.sleep(2000);
driver.get("https://anhtester.com");
WebElement APITesting = driver.findElement(By.xpath("//h3[normalize-space()='API Testing']"));
WebElement WebsiteTesting = driver.findElement(RelativeLocator.with(By.tagName("h3")).toLeftOf(APITesting));
System.out.println(WebsiteTesting.getText());
}
6) Công cụ Chrome DevTools: Trong Selenium 4 họ đã thực hiện một số thay đổi nội bộ trên API. Trong Selenium 3 thì trình điều khiển chrome mở rộng trực tiếp đến lớp trình điều khiển từ xa nhưng Selenium 4 có những thay đổi nhất định về điều này, trong Selenium 4 lớp trình điều khiển chrome mở rộng đến Trình điều khiển Chromium Driver. Lớp trình điều khiển Chromium Driver trong Selenium 4 bao gồm các phương thức khác nhau được xác định trước để truy cập công cụ phát triển.
Bằng cách sử dụng API, chúng ta có thể thực hiện thao tác dưới đây:
@Test
public void TC6_Authentication() {
// Authentication url & username & password
String url = "https://the-internet.herokuapp.com/basic_auth";
String username = "admin";
String password = "admin";
// Get the devtools from the running driver and create a session
DevTools devTools = ((HasDevTools) driver).getDevTools();
devTools.createSession();
// Enable the Network domain of devtools
devTools.send(Network.enable(java.util.Optional.of(100000), java.util.Optional.of(100000), java.util.Optional.of(100000)));
String auth = username + ":" + password;
// Encoding the username and password using Base64 (java.util)
String encodeToString = Base64.getEncoder().encodeToString(auth.getBytes());
// Pass the network header -> Authorization : Basic <encoded String>
Map < String, Object > headers = new HashMap < > ();
headers.put("Authorization", "Basic " + encodeToString);
devTools.send(Network.setExtraHTTPHeaders(new Headers(headers)));
// Load the application url
driver.get(url);
Uninterruptibles.sleepUninterruptibly(Duration.ofSeconds(3));
String successFullyLoggedInText = driver.findElement(By.xpath("//p")).getText();
System.out.println(successFullyLoggedInText);
}
7) Auto download Binary của Browser tương ứng: chúng ta không cần chỉ định đường dẫn file binary của Browser. Selenium có tính năng Selenium Manager nó tự quản lý và tự động tải về binary mới nhất.
Cũ: phải cần chỉ định đường dẫn Binary hoặc dùng WebDriverManager:
@BeforeMethod
public void createDriver() {
System.setProperty("webdriver.chrome.driver","D:\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(10));
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
}
@BeforeMethod
public void createDriver() {
WebDriverManager.edgedriver().setup();
driver = new EdgeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(10));
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
}
Mới: Selenium Manager tự tải về nếu không tìm thấy đường dẫn chỉ định Binary
@BeforeMethod
public void createDriver() {
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(10));
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
}
✅ Thư viện Maven trong pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>anhtester.com</groupId>
<artifactId>FeatureSelenium4</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.6.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.github.bonigarcia/webdrivermanager -->
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>5.3.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.6.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.3</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
✅ Mã code với Selenium 4 và TestNG:
import com.google.common.util.concurrent.Uninterruptibles;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.devtools.v107.network.Network;
import org.openqa.selenium.devtools.v107.network.model.Headers;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.support.locators.RelativeLocator;
import org.testng.Assert;
import org.testng.annotations.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.time.Duration;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class NewFeatureSelenium4 {
private WebDriver driver;
@BeforeMethod
public void createDriver() {
//System.setProperty("webdriver.chrome.driver","D:\\chromedriver.exe");
//WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(10));
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
}
@Test
public void TC1_ScreenshotElement() {
driver.get("https://anhtester.com");
WebElement logo = driver.findElement(By.xpath("//a[@class='logo']"));
File file = logo.getScreenshotAs(OutputType.FILE);
File destFile = new File("logo.png");
try {
Files.copy(file.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Test
public void TC2_NewTab() {
driver.get("https://anhtester.com");
driver.switchTo().newWindow(WindowType.TAB);
driver.get("https://google.com");
}
@Test
public void TC3_NewWindow() {
driver.get("https://anhtester.com");
driver.switchTo().newWindow(WindowType.WINDOW);
driver.get("https://google.com");
}
@Test
public void TC4_ObjectLocation() {
driver.get("https://anhtester.com");
WebElement element = driver.findElement(By.xpath("//a[@id='btn-login']"));
System.out.println("Height is: " + element.getRect().getDimension().getHeight());
System.out.println("Width is: " + element.getRect().getDimension().getWidth());
System.out.println("X location: " + element.getRect().getX());
System.out.println("Y location: " + element.getRect().getY());
}
@Test
public void TC5_RelativeLocators() throws InterruptedException {
driver.get("https://rise.fairsketch.com/signin");
WebElement password = driver.findElement(By.id("password"));
WebElement email = driver.findElement(RelativeLocator.with(By.tagName("input")).above(password));
email.clear();
email.sendKeys("anhtester@mailinator.com");
Thread.sleep(2000);
driver.get("https://anhtester.com");
WebElement APITesting = driver.findElement(By.xpath("//h3[normalize-space()='API Testing']"));
WebElement WebsiteTesting = driver.findElement(RelativeLocator.with(By.tagName("h3")).toLeftOf(APITesting));
System.out.println(WebsiteTesting.getText());
}
@Test
public void TC6_Authentication() {
// Authentication username & password
String url = "https://the-internet.herokuapp.com/basic_auth";
String username = "admin";
String password = "admin";
// Get the devtools from the running driver and create a session
DevTools devTools = ((HasDevTools) driver).getDevTools();
devTools.createSession();
// Enable the Network domain of devtools
devTools.send(Network.enable(java.util.Optional.of(100000), java.util.Optional.of(100000), java.util.Optional.of(100000)));
String auth = username + ":" + password;
// Encoding the username and password using Base64 (java.util)
String encodeToString = Base64.getEncoder().encodeToString(auth.getBytes());
// Pass the network header -> Authorization : Basic <encoded String>
Map<String, Object> headers = new HashMap<>();
headers.put("Authorization", "Basic " + encodeToString);
devTools.send(Network.setExtraHTTPHeaders(new Headers(headers)));
// Load the application url
driver.get(url);
Uninterruptibles.sleepUninterruptibly(Duration.ofSeconds(3));
String successFullyLoggedInText = driver.findElement(By.xpath("//p")).getText();
System.out.println(successFullyLoggedInText);
}
@AfterMethod
public void closeDriver() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.quit();
}
}
♻️ Source code Selenium Java TestNG: https://github.com/anhtester/NewFeatureSelenium4
Yeah Anh Tester đã soạn lại các thay đổi mới của Selenium 4 với phiên bản hiện tại là v4.6.0 hy vọng cung cấp các thông tin mới mẽ bổ ích cho các bạn. Chắc chắn còn thiếu nhiều vì An soạn những cái cần cơ bản thường gặp thôi.
An sẽ cập nhật tiếp tục trong thời gian sắp tới khi có phiên bản Selenium mới cũng như những điểm hay đáng chú ý cho mọi người.
Tất cả những thay đổi thì mọi người có thể xem tại đây: https://github.com/SeleniumHQ/selenium/releases
Chúc mọi người code auto test vui khoẻ nhé 🙌
Anh Tester
Đường dẫu khó chân vẫn cần bước đi
Đời dẫu khổ tâm vẫn cần nghĩ thấu