Ngày 18 tháng 5 năm 2024 - Công nghệ máy tính
Cucumber là một công cụ kiểm thử tự động hỗ trợ BDD (Development Driven by Behaviour, phát triển dựa trên hành vi). Bài viết này sẽ bắt đầu bằng cách giới thiệu về BDD, sau đó đi sâu vào các khái niệm liên quan đến Cucumber win 789 club và cuối cùng cung cấp ví dụ minh họa cách sử dụng Cucumber Java để kiểm thử API.
1. Vậy BDD là gì?
BDD là một quy trình phát triển phần mềm, được xem như sự mở rộng của TDD (Test-Driven Development, phát triển dựa trên kiểm thử), nhấn mạnh sự hợp tác chặt chẽ giữa đội ngũ kỹ thuật và đội ngũ nghiệp vụ nhằm đảm bảo phần mềm được phát triển đáp ứng đúng yêu cầu kinh doanh.
Nền tảng của BDD nằm ở việc sử dụng “ngôn ngữ chung” giữa khách hàng và đội ngũ phát triển để mô tả cùng một hệ thống. Điều này giúp tránh những vấn đề phát sinh từ sự không nhất quán trong giao tiếp — điều thường gặp trong quá trình phát triển phần mềm, dẫn đến kết quả cuối cùng không phù hợp với kỳ vọng của khách hàng. Thông qua việc sử dụng ngôn ngữ chung, cả khách hàng lẫn nhà phát triển có thể cùng định nghĩa hành vi của hệ thống để thiết kế theo đúng nhu cầu của khách hàng. Tuy nhiên, chỉ có thiết kế mà thiếu phương pháp xác thực thì cũng không thể chắc chắn rằng sản phẩm đã đạt yêu cầu. Do đó, BDD yêu cầu tích hợp kiểm thử, sử dụng định nghĩa hành vi của hệ thống để xác nhận mã nguồn đã được thực hiện đúng.
Tâm điểm của BDD chính là thiết kế, trong đó việc định nghĩa hành vi của hệ thống là nhiệm vụ chính, và mô tả hành vi này chính là tiêu chuẩn kiểm thử.
Tiếp theo, chúng ta sẽ tìm hiểu thêm một số khái niệm cốt lõi của BDD.
1.1 Các khái niệm cốt lõi
-
Chuyện người dùng (User Story): BDD thường mô tả yêu cầu phần mềm thông qua chuyện người dùng. Những câu chuyện này thường được viết bằng ngôn ngữ tự nhiên dễ hiểu, miêu tả nhu cầu cụ thể của người dùng trong từng tình huống cụ thể.
-
Kịch bản (Scenario): Mỗi chuyện người dùng bao gồm nhiều kịch bản, dùng để mô tả chi tiết các tình huống sử dụng cụ thể của người dùng. Những kịch bản này được viết theo định dạng Given-When-Then (Cho trước-Khi-Điều mong đợi), rõ ràng nêu ra trạng thái ban đầu của hệ thống (Given), sự kiện được kích hoạt (When) và kết quả mong muốn (Then).
-
Ví dụ (Example): Các ví dụ cụ thể được sử dụng để giải thích chi tiết hơn về hành vi được mô tả trong các kịch bản. Những ví dụ này giúp các nhà phát triển hiểu rõ hơn và thực hiện tốt hơn nhu cầu của người dùng.
Sau đây là các bước thực hiện BDD cụ thể.
i88win 1.2 Các bước thực hiện BDD
-
Xác định yêu cầu: Đội ngũ phát triển (bao gồm cả chuyên viên kiểm thử) làm việc cùng với nhân viên nghiệp vụ để thảo luận và viết ra các chuyện người dùng và kịch bản. Điều này đảm bảo tất cả mọi người đều có sự hiểu biết nhất quán về yêu cầu.
-
Viết trường hợp kiểm thử: Dựa trên các chuyện người dùng và kịch bản, các trường hợp kiểm thử tự động được viết ra (ví dụ sử dụng các công cụ hỗ trợ BDD như Cucumber, JBehave).
-
Phát triển chức năng: Các lập trình viên viết mã code để thực hiện các chức năng đáp ứng yêu cầu. Quá trình phát triển gắn liền chặt chẽ với kiểm thử để đảm bảo mã nguồn đáp ứng đúng yêu cầu.
-
Thực thi trường hợp kiểm thử: Kiểm thử tự động được sử dụng để xác nhận tính chính xác của chức năng, qua đó đảm bảo rằng các tính năng mới không làm hỏng các chức năng cũ (kiểm thử hồi quy).
-
Lặp lại vòng đời: Quá trình phát triển thường diễn ra theo chu kỳ lặp lại, mỗi lần lặp đều bao gồm việc thảo luận yêu cầu, viết trường hợp kiểm thử, phát triển chức năng và thực thi các trường hợp kiểm thử.
Dưới đây là một số lợi ích mà BDD mang lại.
1.3 Lợi ích của BDD
-
Nâng cao hiệu suất giao tiếp: Việc sử dụng các câu chuyện người dùng và kịch bản đồng nhất giúp đội ngũ nghiệp vụ và đội ngũ phát triển giao tiếp và hiểu rõ hơn về yêu cầu.
-
Giảm thiểu lỗi: Mô tả yêu cầu rõ ràng và kiểm thử tự động có thể giảm đáng kể lỗi phát sinh từ việc thay đổi yêu cầu.
-
Nâng cao chất lượng phần mềm: Kiểm thử tự động liên tục có thể đảm bảo chất lượng và độ ổn định của phần mềm.
-
Tăng cường sự hợp tác giữa các nhóm: Khuyến khích sự hợp tác giữa các nhóm chức năng khác nhau, giúp cải thiện hiệu quả tổng thể của nhóm và sự hài lòng trong công việc.
Hiểu được các khái niệm cơ bản của BDD và biết rằng Cucumber là một công cụ hỗ trợ kiểm thử BDD, bây giờ chúng ta hãy xem cách sử dụng Cucumber để viết các trường hợp kiểm thử.
cwin222 2. Làm thế nào để sử dụng Cucumber để viết các trường hợp kiểm thử?
Tệp đặc điểm Cucumber bao gồm nhiều kịch bản, mỗi kịch bản được viết theo định dạng Given-When-Then. Ngôn ngữ cú pháp mà Cucumber sử dụng gọi là Gherkin.
Dưới đây là một ví dụ về tệp đặc điểm Cucumber được sử dụng để kiểm thử chức năng đăng nhập:
Đặc điểm: Chức năng Đăng nhập
Người dùng có thể đăng nhập thành công vào hệ thống
Kịch bản: Người dùng có thể đăng nhập thành công khi nhập tên người dùng và mật khẩu đúng
Cho trước Người dùng mở trang đăng nhập
Khi Người dùng nhập tên người dùng "test" và mật khẩu "password"
Và Người dùng nhấn nút đăng nhập
Thì Người dùng đăng nhập thành công vào hệ thống
Cucumber hỗ trợ việc viết mã kiểm thử tương ứng cho từng bước Given-When-Then (được gọi là Step Definitions).
Một đoạn mã Step Definition được viết bằng ngôn ngữ Java như sau:
@ChoTrước("Người dùng mở trang đăng nhập")
public void moTrangDangNhap() {
driver.get(URLConstants.DANG_NHAP_URL);
}
Sau khi thực thi hoàn tất, Cucumber sẽ tạo ra báo cáo để hiển thị kết quả thành công hay thất bại của mỗi kịch bản, qua đó xác nhận phần mềm có đáp ứng đúng yêu cầu hay không.
Sau khi giới thiệu các kiến thức cơ bản về BDD và Cucumber, bây giờ chúng ta sẽ thử nghiệm việc sử dụng Cucumber để kiểm thử API.
3. Làm thế nào để sử dụng Cucumber để kiểm thử API?
Dưới đây là ví dụ về cách sử dụng Cucumber để kiểm thử API GitHub Issues.
Dự án ví dụ sử dụng các phiên bản sau:
JDK: BellSoft Liberica 17.0.7
Maven: 3.9.2
Cucumber Java: 7.17.0
Do Cucumber chỉ hỗ trợ viết tệp đặc điểm và gắn kết mã nguồn, nên việc viết mã kiểm thử cụ thể cần sử dụng các công cụ khác. Trong ví dụ này, chúng tôi sử dụng REST Assured để kiểm thử API (cách sử dụng REST Assured chi tiết hơn có thể tham khảo bài viết trước đây của tôi “Làm thế nào để sử dụng REST Assured để kiểm thử API?”).
3.1 Cấu trúc dự án và phụ thuộc Maven
Dự án kiểm thử ví dụ này sử dụng Maven để quản lý, cấu trúc như sau:
cucumber-api-test-demo
├─ src/test
│ ├─ java
│ │ └─ com.example.tests
│ │ ├─ stepdefs
│ │ │ └─ CreateIssueStep.java
│ │ ├─ utils
│ │ │ └─ ConfigUtil.java
│ │ └─ TestRunner.java
│ └─ resources
│ ├─ features
│ │ └─ github-issues.feature
│ └─ config.properties
└─ pom.xml
Như có thể thấy, tệp đặc điểm Cucumber nằm trong thư mục src/test/resources/features
, mã nguồn nằm trong thư mục src/test/java/com/example/tests
. TestRunner.java
là file khởi chạy chương trình; ConfigUtil.java
trong gói utils
là lớp công cụ cho tập tin cấu hình; các lớp Java trong gói stepdefs
chịu trách nhiệm thực hiện các bước được định nghĩa trong các tệp đặc điểm.
Dự án ví dụ này sử dụng các phụ thuộc sau:
<phụ_thuộc_vật>
<!-- cucumber -->
<phụ_thuộc>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</phụ_thuộc>
<phụ_thuộc>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</phụ_thuộc>
<!-- rest assured -->
<phụ_thuộc>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>${rest-assured.version}</version>
<scope>test</scope>
</phụ_thuộc>
<!-- jackson-databind -->
<phụ_thuộc>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.1</version>
<scope>test</scope>
</phụ_thuộc>
<!-- junit -->
<phụ_thuộc>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</phụ_thuộc>
</phụ_thuộc_vật>
Ngoài hai gói cốt lõi của Cucumber (cucumber-java
, cucumber-junit
) và JUnit 5, chúng tôi còn sử dụng rest-assured
để gửi yêu cầu API và thu thập phản hồi, cũng như jackson-databind
để xử lý JSON trong yêu cầu của rest-assured
.
Chúng tôi cũng sử dụng plugin maven-cucumber-reporting
để tạo báo cáo HTML:
<plugin>
<groupId>net.masterthought</groupId>
<artifactId>maven-cucumber-reporting</artifactId>
<version>5.8.1</version>
</plugin>
3.2 Tập tin Features
Dự án ví dụ này chỉ có một kịch bản kiểm thử API GitHub Issues: Tạo một Issue mới. Nội dung tệp github-issues.feature
như sau:
# src/test/resources/features/github-issues.feature
Đặc điểm: Kiểm thử API GitHub Issues
Kịch bản: Tạo một Issue mới
Cho trước Tạo một Issue mới có tiêu đề "Cucumber API Test"
Thì Mã phản hồi là 201 và tiêu đề Issue trong thân phản hồi là "Cucumber API Test"
Như có thể thấy, đối với kịch bản “Tạo một Issue mới”, chúng tôi sử dụng Cho trước
để đặt điều kiện và gửi yêu cầu, sử dụng Thì
để xác nhận kết quả phản hồi.
3.3 Nguồn mã Step Definitions
Dưới đây là mã nguồn Java tương ứng với các bước được liệt kê trong tệp github-issues.feature
:
// src/test/java/com/example/tests/stepdefs/CreateIssueStep.java
package com.example.tests.stepdefs;
// ...
public class CreateIssueStep {
private int maPhanHoi;
private String noiDungPhanHoi;
@ChoTrước("Tạo một Issue mới có tiêu đề {string}")
public void taoMotIssue(String tieuDe) {
// Yêu cầu
Map<String, Object> noiDungYeuCau = prepareRequestBody(tieuDe);
// Phản hồi
Response phanHoi = given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.header("Authorization", "Bearer " + ConfigUtil.getProperty("GITHUB_TOKEN"))
.body(noiDungYeuCau)
.post("/issues")
.then()
.extract()
.response();
// Trích xuất
this.maPhanHoi = phanHoi.getStatusCode();
this.noiDungPhanHoi = phanHoi.asString();
}
@Thì("Mã phản hồi là {int} và tiêu đề Issue trong thân phản hồi là {string}")
public void phanHoiCanDuocXacThuc(int maPhanHoi, String tieuDe) {
// Trích xuất trường
String tieuDeIssue = from(noiDungPhanHoi).getString("tieuDe");
// Kiểm tra
assertThat(maPhanHoi, equalTo(this.maPhanHoi));
assertThat(tieuDe, equalTo(tieuDeIssue));
}
private Map<String, Object> prepareRequestBody(String tieuDe) {
Map<String, Object> noiDungYeuCau = new HashMap<>();
noiDungYeuCau.put("tieuDe", tieuDe);
noiDungYeuCau.put("noiDung", "test");
return noiDungYeuCau;
}
}
Như có thể thấy, chúng tôi đã thêm các từ khóa @ChoTrước
và @Thì
cho các phương thức tương ứng với các bước trong tệp đặc điểm. Trong phương thức @ChoTrước
, chúng tôi sử dụng REST Assured để xây dựng và gửi yêu cầu, trong khi phương thức @Thì
kiểm tra kết quả phản hồi.
3.4 File khởi chạy chương trình
Dưới đây là file khởi chạy chương trình của dự án kiểm thử:
// src/test/java/com/example/tests/TestRunner.java
package com.example.tests;
// ...
@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/resources/features", plugin = {"json:target/cucumber.json"})
public class TestRunner {
@BeforeClass
public static void setUp() {
baseURI = ConfigUtil.getProperty("GITHUB_BASE_URI");
}
}
Như có thể thấy, chúng tôi đã thêm chú thích @RunWith(Cucumber.class)
để chỉ định việc thực thi do Cucumber chịu trách nhiệm; ngoài ra, chúng tôi cũng sử dụng chú thích @CucumberOptions
để chỉ định thư mục chứa tệp đặc điểm và thư mục chứa file JSON kết quả kiểm thử.
Phương thức tĩnh setUp()
chịu trách nhiệm thiết lập giá trị toàn cục baseURI
của REST Assured, giúp không phải viết URL đầy đủ khi gửi yêu cầu trong Step Definitions.
3.5 Thực thi kiểm thử và hiển thị báo cáo
Sau khi viết xong các trường hợp kiểm thử, bạn có thể sử dụng lệnh Maven sau để thực thi kiểm thử:
mvn clean verify
File báo cáo HTML sẽ được tạo ra trong thư mục sau:
target/cucumber-report-html
Mở file bằng trình duyệt, bạn sẽ thấy kết quả như sau:
Như có thể thấy, tất cả các bước được định nghĩa trong tệp đặc điểm đều vận hành bình thường, kiểm thử đã vượt qua.
4. Kết luận
Bài viết này là một cái nhìn sơ lược về Cucumber. Vì Cucumber là một công cụ kiểm thử hỗ trợ BDD, bài viết đã bắt đầu bằng cách giới thiệu các khái niệm cơ bản của BDD, sau đó đi sâu vào kiến thức cơ bản về Cucumber và cuối cùng cung cấp ví dụ minh họa cách sử dụng Cucumber để kiểm thử một API GitHub.
Dự án ví dụ hoàn chỉnh đã được đưa lên GitHub cá nhân của tôi, mời bạn quan tâm hoặc Fork.
[1] Tài liệu Cucumber: Hướng dẫn - [2] Bách khoa toàn thư Baidu: Phát triển dựa trên hành vi - [3] Lê Lê: Làm thế nào để sử dụng REST Assured để kiểm thử API? - [4] Tài liệu GitHub: Các điểm cuối REST API cho issues -
#AutomationTesting #Cucumber #Java