Cách Sử Dụng Serenity BDD Để Thực Hiện Kiểm Thử Giao Diện Người Dùng (UI) - game bài đổi thưởng tặng quà khởi nghiệp

| Mar 10, 2025 min read

Ngày 12 tháng 6 năm 2024 | Máy Tính

Serenity BDD (Behavior Driven Development, Phát Triển Hành Vi) là một khung kiểm thử tự động hóa hỗ trợ ngôn ngữ Java. Khung Serenity BDD mạnh mẽ, tích hợp nhiều tiêu chuẩn kiểm thử chung của ngành và có khả năng làm việc với các mô hình trang web (Page Object Model). Nó cũng tương thích với các khung kiểm thử phổ biến như JUnit, Cucumber, Selenium và JBehave. Ngoài ra, Serenity BDD cung cấp báo cáo chi tiết về kết quả từng bước thực thi, chụp ảnh màn hình trang, thời gian xử lý và mức độ bao phủ tổng thể của quá trình kiểm thử.

Bài viết này minh họa cách sử dụng Serenity BDD, JUnit 5 và Selenium để kiểm thử giao diện người dùng (UI) trên GitHub thông qua kịch bản đăng nhập và tạo Issue.

Phiên bản JDK, Maven và Serenity BDD được sử dụng trong ví dụ này là:

JDK: Amazon Corretto 17.0.8
Maven: 3.9.2
Serenity BDD: 4.1.20

1. Cấu Trúc Dự Án Và Phụ Thuộc Maven

Cấu trúc của dự án ví dụ như sau:

serenity-bdd-ui-test-demo
├─ src/test
│  ├─ java
│  │  └─ com.example.tests
│  │    ├─ conf
│  │    │  └─ WebDriverConf.java
│  │    ├─ pages
│  │    │  ├─ LoginPage.java
│  │    │  └─ CreateIssuePage.java
│  │    ├─ utils
│  │    │  ├─ GoogleAuthenticatorUtil.java
│  │    │  └─ ConfigUtil.java
│  │    └─ GitHubIssueTest.java
│  └─ resources
│    └─ config.properties
└─ pom.xml

Dưới đây là chức năng của từng gói, thư mục và tệp tin:

  • Gói pages: Chứa các lớp đối tượng trang (Page Object), chịu trách nhiệm gọi các thao tác Selenium trên trình duyệt.
  • Gói utils: Chứa các lớp công cụ. Ví dụ, GoogleAuthenticatorUtil.java dùng để sinh mã xác thực từ Google Authenticator; ConfigUtil.java dùng để đọc cấu hình từ file.
  • Gói conf: Chứa các lớp cấu hình. Ví dụ, WebDriverConf.java cấu hình cho Selenium WebDriver.
  • Tệp GitHubIssueTest.java: Đây là lớp kiểm thử đơn vị theo chuẩn JUnit 5.
  • Tệp resources/config.properties: File cấu hình chứa tài khoản GitHub, mật khẩu và khóa bí mật Google Authentication.

Dự án này sử dụng các phụ thuộc sau:

<dependencies>
  <!-- serenity bdd -->
  <dependency>
    <groupId>net.serenity-bdd</groupId>
    <artifactId>serenity-core</artifactId>
    <version>${serenity-bdd.version}</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>net.serenity-bdd</groupId>
    <artifactId>serenity-junit5</artifactId>
    <version>${serenity-bdd.version}</version>
    <scope>test</scope>
  </dependency>
  <!-- google authenticator -->
  <dependency>
    <groupId>com.warrenstrange</groupId>
    <artifactId>googleauth</artifactId>
    <version>1.5.0</version>
    <scope>test</scope>
  </dependency>
  <!-- logback -->
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.5.6</version>
    <scope>test</scope>
  </dependency>
  <!-- junit 5 -->
  <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>${junit.version}</version>
    <scope>test</scope>
  </dependency>
</dependencies>

Ngoài các phụ thuộc chính như JUnit 5 và Serenity BDD, dự án còn sử dụng googleauth để sinh mã xác thực và logback-classic để in nhật ký.

Thêm vào đó, chúng ta cũng sử dụng plugin maven-compiler-plugin để biên dịch mã nguồn và plugin serenity-maven-plugin để tạo báo cáo HTML:

<plugins>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.13.0</version>
    <configuration>
      <source>17</source>
      <target>17</target>
    </configuration>
  </plugin>
  <plugin>
    <groupId>net.serenity-bdd.maven.plugins</groupId>
    <artifactId>serenity-maven-plugin</artifactId>
    <version>${serenity-bdd.version}</version>
    <executions>
      <execution>
        <id>serenity-reports</id>
        <phase>post-integration-test</phase>
        <goals>
          <goal>aggregate</goal>
        </goals>
      </execution>
    </executions>
    <dependencies>
      <dependency>
        <groupId>net.serenity-bdd</groupId>
        <artifactId>serenity-single-page-report</artifactId>
        <version>${serenity-bdd.version}</version>
      </dependency>
    </dependencies>
  </plugin>
</plugins>

2. Lớp Đối Tượng Trang (Page Object Classes)

Gói pages chứa các lớp đối tượng trang, chịu trách nhiệm gọi Selenium để thực hiện các thao tác trên trình duyệt. Nội dung của lớp LoginPage.java như sau:

package com.example.tests.pages;

import com.example.tests.utils.ConfigUtil;
import com.example.tests.utils.GoogleAuthenticatorUtil;
import net.serenitybdd.core.pages.PageComponent;
import org.openqa.selenium.By;

public class LoginPage extends PageComponent {
    private static final String LOGIN_URL = "https://github.com/login";
    private static final By USERNAME_ELEM = By.id("login_field");
    private static final By PASSWORD_ELEM = By.id("password");
    private static final By SIGN_IN_BUTTON = By.name("commit");
    private static final By TOTP_ELEM = By.id("otp");

    public void login() {
        openUrl(LOGIN_URL);
        $(USERNAME_ELEM).sendKeys(ConfigUtil.getProperty("GITHUB_USERNAME"));
        $(PASSWORD_ELEM).sendKeys(ConfigUtil.getProperty("GITHUB_PASSWORD"));
        $(SIGN_IN_BUTTON).click();
        int code = GoogleAuthenticatorUtil.getTotpCode(ConfigUtil.getProperty("GITHUB_TOTP_SECRET"));
        $(TOTP_ELEM).sendKeys(String.valueOf(code));
    }
}

Lớp này kế thừa từ PageComponent, lớp đóng gói các thao tác Selenium để dễ dàng hơn khi tương tác với các phần tử trên trang. Phương thức login() thực hiện toàn bộ quy trình đăng nhập GitHub: mở trang đăng nhập, nhập tên người dùng và mật khẩu, nhấn nút “Đăng Nhập”, và nhập mã xác thực.

Lớp CreateIssuePage có nội dung như sau:

package com.example.tests.pages;

import com.example.tests.utils.ConfigUtil;
import net.serenitybdd.core.pages.PageComponent;
import org.openqa.selenium.By;

public class CreateIssuePage extends PageComponent {
    private static final String CREATE_ISSUE_URL = "/issues/new";
    private static final By INPUT_TITLE_ELEM = By.xpath("//input[@id='issue_title']");
    private static final By SUBMIT_BUTTON = By.xpath("//button[contains(text(), 'Submit new issue')]");

    public void createIssue(String title) {
        openUrl(ConfigUtil.getProperty("GITHUB_REPO") + CREATE_ISSUE_URL);
        waitForRenderedElementsToBePresent(INPUT_TITLE_ELEM);
        $(INPUT_TITLE_ELEM).sendKeys(title);
        $(SUBMIT_BUTTON).click();
    }
}

Lớp này chứa các thuộc tính và hành vi liên quan đến trang tạo Issue. Phương thức createIssue() mở trang tạo Issue, nhập tiêu đề và nhấn nút gửi.

3. Các Lớp Cấu Hình Và Công Cụ

Lớp cấu hình WebDriverConf.java trong gói conf thiết lập toàn cục cho Selenium WebDriver:

package com.example.tests.conf;

import net.serenitybdd.annotations.Managed;
import org.openqa.selenium.WebDriver;

public class WebDriverConf {
    @Managed(driver = "chrome")
    private WebDriver driver;
}

Chúng ta sử dụng chú thích @Managed để đánh dấu thuộc tính WebDriver, chỉ định rằng Serenity sẽ quản lý vòng đời của WebDriver (tải xuống WebDriver phù hợp nếu chưa cài đặt và tự động đóng trình duyệt sau khi chạy).

Lớp công cụ GoogleAuthenticatorUtil.java trong gói utils dùng để sinh mã xác thực từ Google Authenticator:

package com.example.tests.utils;

import com.warrenstrange.googleauth.GoogleAuthenticator;

public class GoogleAuthenticatorUtil {
    private static final GoogleAuthenticator authenticator = new GoogleAuthenticator();

    public static int getTotpCode(String secret) {
        return authenticator.getTotpPassword(secret);
    }
}

Lớp này cung cấp phương thức tĩnh để sinh mã xác thực dựa trên khóa bí mật.

Lớp công cụ khác ConfigUtil.java dùng để đọc file cấu hình:

package com.example.tests.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class ConfigUtil {
    private static final String FILE_NAME = "/config.properties";
    private static final Properties PROPERTIES = new Properties();

    static {
        loadProperties(); [tải game 789win](/post/7869/) 
    }

    private static void loadProperties() {
        try (InputStream is = ConfigUtil.class.getResourceAsStream(FILE_NAME)) {
            PROPERTIES.load(is);
        } catch (IOException e) {
            throw new RuntimeException("Không thể tải config.properties", e);
        }
    }

    public static String getProperty(String key) {
        return PROPERTIES.getProperty(key);
    } [game bài đổi thưởng tặng quà khởi nghiệp](https://www.ennisi.com) 
}

File cấu hình config.properties như sau:

GITHUB_USERNAME=leileiluoluo
GITHUB_PASSWORD=xxxxxx
GITHUB_TOTP_SECRET=xxxxxx
GITHUB_REPO=

4. Lớp Kiểm Thử Đơn Vị

Lớp kiểm thử GitHubIssueTest.java khởi tạo kịch bản kiểm thử Issue trên GitHub:

package com.example.tests;

import com.example.tests.pages.CreateIssuePage;
import com.example.tests.pages.LoginPage;
import net.serenitybdd.core.Serenity;
import net.serenitybdd.junit5.SerenityJUnit5Extension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.startsWith;

@ExtendWith(SerenityJUnit5Extension.class)
public class GitHubIssueTest {
    private LoginPage loginPage;
    private CreateIssuePage createIssuePage;

    @Test
    public void testIssueCreation() {
        loginPage.login();
        String title = "Serenity UI Test";
        createIssuePage.createIssue(title);
        Serenity.reportThat("Kiểm tra tiêu đề", () -> 
            assertThat(createIssuePage.getTitle(), startsWith(title)));
    }
}

Đây là một lớp kiểm thử đơn vị JUnit 5, đánh dấu bằng chú thích @ExtendWith(SerenityJUnit5Extension.class) để sử dụng Serenity JUnit 5 Extension. Phương thức testIssueCreation() thực hiện kiểm thử đăng nhập và tạo Issue, sau đó xác nhận tiêu đề của Issue đã được tạo đúng.

5. Chạy Dự Án Và Xem Báo Cáo

Trước khi chạy, hãy đảm bảo máy của bạn có trình duyệt Chrome và ChromeDriver tương ứng. Nếu chưa cài đặt, Serenity sẽ tự động tải xuống phiên bản phù hợp.

Bạn có thể chạy dự án trực tiếp trong IntelliJ IDEA hoặc sử dụng lệnh sau trong dòng lệnh:

mvn clean verify

Sau khi chạy xong, báo cáo HTML sẽ được tạo ở thư mục target/site/serenity.

6. Kết Luận

Bài viết này minh họa cách sử dụng Serenity BDD, JUnit 5 và Selenium để kiểm thử UI trên GitHub thông qua kịch bản đăng nhập và tạo Issue. Dự án hoàn chỉnh đã được đẩy lên GitHub, mời bạn theo dõi hoặc fork.

#Tự Động Hóa Kiểm Thử #Java #Selenium