Những tính năng mới trong Selenium 4

Sau một khoảng thời gian Selenium 4 ra mắt thì An đã chính thức dùng nó và thấy rất hay trong phiên bản mới này.

Trong bài viết này Anh Tester sẽ giới thiệu đến với bạn một vài tính năng mới trong Selenium 4 đặc biệt là Selenium WebDriver để các bạn có thể cân nhắc nâng cấp nhé !!

1. Selenium là gì ??

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.

2. Sự thay đổi trong Selenium 4


🔆 Giao thức W3C WebDriver

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 ConsutirumW3C 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.


✅ Kiến trúc của Selenium 3:

Những tính năng mới trong Selenium 4 | Anh Tester

 

✅ Kiến trúc của Selenium 4:

Những tính năng mới trong Selenium 4 | Anh Tester


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.


3. Tải Selenium 4 hoặc nâng cấp

Để 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


4. Tính năng mới trong Selenium 4


Các tính năng xoá bỏ từ bản Selenium 3:

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 OperaPhantomJS

Hiện tại chỉ còn hỗ trợ như sau:

  • Firefox – FirefoxOptions
  • Chrome – ChromeOptions
  • Internet Explorer (IE) – InternetExplorerOptions
  • Microsoft Edge – EdgeOptions
  • Safari – SafariOptions

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

 

🔆 Các tính năng mới bổ sung trong Selenium 4

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.

  • below(): để tìm phần tử bên dưới một phần tử web chỉ định.
  • toLeftOf(): nó tìm phần tử web phía bên trái của phần tử web chỉ định.
  • toRightOf(): nó tìm phần tử web phía bên phải phần tử web chỉ định.
  • above(): nó tìm phần tử nằm bên trên phần tử được chỉ định.
  • near(): nó tìm một phần tử cách xa (khoảng 50 pixel) từ một phần tử web được chỉ định.


@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:

  • Enables network offline (Nó cho phép bật mạng ngoại tuyến)
  • Enable Network Online (Bật mạng trực tuyến)
  • Get console log
  • Network Interception: chặn, xác thực và sửa đổi các yêu cầu và phản hồi của mạng. Thêm tiêu đề bổ sung, yêu cầu không thành công, sửa đổi nội dung yêu cầu / phản hồi, v.v.

Ví dụ dùng DevTool để xử lý Authentication:

@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));
    }

 

🔆 Toàn bộ mã nguồn code mẫu cho Selenium 4 bên trên


✅ 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