Cách Sử Dụng Serenity BDD Để Kiểm Tra API - iwin58

| May 18, 2025 min read

19 tháng 6 năm 2024 Công nghệ thông tin

Trong bài trước “Cách Sử Dụng Serenity BDD Để Kiểm Tra Giao Diện Người Dùng (UI)”, chúng tôi đã giới thiệu cách sử dụng Serenity BDD cùng Selenium để kiểm tra giao diện web. Tuy nhiên, Serenity BDD không chỉ dừng lại ở việc kiểm tra UI mà còn có thể áp dụng để kiểm tra các REST API. Bài viết này sẽ trình bày cách sử dụng Serenity BDD kết hợp với REST Assured để tiến hành kiểm tra API.

REST Assured là một thư viện Java rất dễ sử dụng và chuyên dụng cho việc kiểm tra các API kiểu RESTful, trước đây chúng ta đã có bài viết riêng về cách sử dụng nó (Cách Sử Dụng REST Assured Để Kiểm Tra API). Trong bài viết này, chúng ta sẽ không đi sâu vào các khái niệm cơ bản của REST Assured mà chỉ tập trung vào việc tích hợp giữa Serenity BDD và REST Assured.

Tình huống kiểm thử được nhắm tới:

“Tiến hành gọi REST API GitHub để tạo một Issue”. Dự án kiểm thử sử dụng Maven làm công cụ quản lý.

Dưới đây là phiên bản của JDK, Maven và Serenity BDD được sử dụng trong dự án kiểm thử:

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

Cấu trúc thư mục của dự án kiểm thử như sau:

serenity-bdd-api-test-demo
├─ src/test
│  ├─ java
│  │  └─ com.example.tests
│  │    ├─ actions
│  │    │  └─ CreateIssueAction.java
│  │    ├─ utils
│  │    │  └─ ConfigUtil.java
│  │    └─ GitHubIssueTest.java
│  └─ resources
│    └─ config.properties
└─ pom.xml

Cấu trúc thư mục của dự án rất đơn giản: gói actions dùng để chứa các lớp thực Soi Cầu Nohu87 hiện các hành động, các phương thức trong lớp này có thể đánh dấu bằng các chú thích (@Given, @When@Then) tương ứng với giai đoạn chuẩn bị, thực thi và xác nhận; gói utils dùng để chứa các lớp công cụ, ví dụ như ConfigUtil.java đọc các biến từ tệp cấu hình; tệp resources/config.properties là tệp cấu hình chính, lưu trữ URL cơ sở của kho cần kiểm tra và token GitHub.

Dưới sv88 comvn đây là các phụ thuộc (dependencies) được sử dụng trong dự án kiểm thử:

<!-- 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-rest-assured</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>
<!-- 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>

Như có thể thấy, Serenity BDD đóng vai trò là phụ thuộc chính, bao gồm các chức năng cơ bản của Serenity, REST Assured cũng như các mô-đun liên quan đến sự tích hợp giữa Serenity và JUnit 5. Ngoài ra, Logback và JUnit 5 cũng được thêm vào để hỗ trợ in nhật ký và thực thi các bài kiểm thử đơn vị.

Ngoài các phụ thuộc trên, hai plugin cũng được tham chiếu trong tệp pom.xml: maven-compiler-pluginserenity-maven-plugin, lần lượt được sử dụng để biên dịch dự án và tạo báo cáo kiểm thử.

Dưới đây là phân tích chi tiết về phần mã nguồn quan trọng.

2 Phân Tích Mã Nguồn

2.1 Lớp Action

Chúng tôi đã bao bọc logic tương ứng với các phần @Given, @When@Then trong mô hình BDD vào lớp Action. Lớp CreateIssueAction.java chịu trách nhiệm xử lý tất cả các hoạt động liên quan đến việc tạo Issue.

// src/test/java/com/example/tests/actions/CreateIssueAction.java
package com.example.tests.actions;

import com.example.tests.utils.ConfigUtil;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import net.serenitybdd.core.steps.UIInteractions;
import java.util.HashMap;
import java.util.Map;

import static io.restassured.path.json.JsonPath.from;
import static net.serenitybdd.rest.SerenityRest.given;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

public class CreateIssueAction extends UIInteractions {
    private int statusCode;
    private String responseBody;

    @Given("Tạo một Issue với tiêu đề {0}")
    public void createIssue(String title) {
        // Chuẩn bị request body
        Map<String, Object> requestBody = prepareRequestBody(title);

        // Thực hiện yêu cầu POST
        Response response = given()
            .contentType(ContentType.JSON)
            .accept(ContentType.JSON)
            .header("Authorization", "Bearer " + ConfigUtil.getProperty("GITHUB_TOKEN"))
            .body(requestBody)
            .post("/issues")
            .then()
            .extract()
            .response();

        // Lưu trạng thái phản hồi
        this.statusCode = response.getStatusCode();
        this.responseBody = response.asString();
    }

    @Then("Mã phản hồi là {0} và tiêu đề Issue trong phản hồi là {1}")
    public void responseShouldBeValid(int expectedStatusCode, String expectedTitle) {
        // Trích xuất trường tiêu đề từ phản hồi
        String issueTitle = from(responseBody).getString("title");

        // Xác nhận dữ liệu
        assertThat(expectedStatusCode, equalTo(this.statusCode));
        assertThat(expectedTitle, equalTo(issueTitle));
    }

    private Map<String, Object> prepareRequestBody(String title) {
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("title", title);
        return requestBody;
    }
}

Lớp CreateIssueAction kế thừa từ lớp UIInteractions của Serenity. Mặc dù tên gọi của lớp này có chữ “UI”, nhưng điều đó không có nghĩa là nó chỉ được sử dụng cho các thao tác liên quan đến giao diện người dùng. Thay vào đó, nó có khả năng tương tác cả với API.

Phương thức createIssue() được đánh dấu bằng chú thích @Given, bên trong nó sử dụng REST Assured để gửi yêu cầu tạo Issue và lưu lại kết quả phản hồi. Phương thức responseShouldBeValid() được đánh dấu bằng chú thích @Then, chịu trách nhiệm trích xuất tiêu đề từ phản hồi và thực hiện xác nhận.

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

Điểm nhập của bài kiểm thử là một lớp đơn vị kiểm thử JUnit 5 bình thường. Một lớp kiểm thử có thể chứa một nhóm các bài kiểm thử liên quan.

Phần kiểm thử liên quan đến việc tạo Issue được đặt trong lớp GitHubIssueTest, mã nguồn của lớp này như sau:

// src/test/java/com/example/tests/GitHubIssueTest.java
package com.example.tests;

import com.example.tests.actions.CreateIssueAction;
import com.example.tests.utils.ConfigUtil;
import io.restassured.RestAssured;
import net.serenitybdd.junit5.SerenityJUnit5Extension;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(SerenityJUnit5Extension.class)
public class GitHubIssueTest {
    private CreateIssueAction createIssueAction;

    @BeforeAll
    public static void setUp() {
        RestAssured.baseURI = ConfigUtil.getProperty("GITHUB_BASE_URI");
    }

    @Test
    public void testIssueCreation() {
        String title = "Kiểm Thử API Với Serenity";
        createIssueAction.createIssue(title);
        createIssueAction.responseShouldBeValid(201, title);
    }
}

Như có thể thấy, lớp này được đánh dấu bằng chú thích @ExtendWith(SerenityJUnit5Extension.class), biểu thị rằng việc khởi chạy sẽ do mở rộng Serenity JUnit5 đảm nhận. Sau đó, trong phương thức setUp(), đường dẫn cơ sở URI được thiết lập. Trong phương thức kiểm thử testIssueCreation(), chúng ta gọi createIssueAction để tạo Issue và xác nhận kết quả.

3 Chạy Chương Trình Và Xem Báo Cáo

Dự án mẫu này có thể chạy trực tiếp trong IntelliJ IDEA hoặc thông qua dòng lệnh với câu lệnh sau:

mvn clean verify

Sau khi chạy xong, một báo cáo HTML sẽ được sinh ra trong thư mục target/site/serenity. Khi mở báo cáo, bạn sẽ thấy kết quả như sau:

![Báo cáo HTML được tạo bởi Serenity]

Báo cáo hiển thị thông tin rất chi tiết, bao gồm tình trạng thực thi của từng bước và ghi lại URL yêu cầu, nội dung yêu cầu và phản hồi cho các bước liên quan đến API.

4 Kết Luận

Tóm lại, bài viết này đã giới thiệu cách sử dụng Serenity BDD cùng REST Assured để kiểm tra API với tình huống kiểm thử là tạo một Issue trên GitHub.

Dự án mẫu hoàn chỉnh đã được đẩy lên GitHub, bạn có thể theo dõi hoặc Fork.

[1] Serenity BDD: Bài Kiểm Tra API Đầu Tiên - [2] Cách Sử Dụng Serenity BDD Để Kiểm Tra Giao Diện Người Dùng (UI) - [3] Cách Sử Dụng REST Assured Để Kiểm Tra API -

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