21 tháng hj88 6 năm 2024 Công nghệ thông tin
Chúng ta đều biết rằng Serenity BDD và Cucumber Java là hai khung kiểm thử tự động hóa phổ biến được sử dụng cho ngôn ngữ lập trình Java. Khung Serenity BDD có nhiều tính năng mạnh mẽ, hỗ trợ tích hợp các mẫu thiết kế kiểm thử phần mềm thông dụng trong ngành (như mô hình trang đối tượng, Screenplay Pattern, v.v.), trong khi một lợi thế lớn của khung Cucumber là khả năng viết kịch bản kiểm thử bằng cách sử dụng cú pháp tương tự ngôn ngữ tự nhiên (Gherkin syntax). Do đó, việc tích hợp hai công cụ này sẽ mang lại khả năng cộng hưởng mạnh mẽ.
Trong các bài trước, chúng tôi đã giới thiệu cách sử dụng Serenity BDD để thực hiện kiểm thử giao diện người dùng (UI) và cách sử dụng Cucumber Java để kiểm thử UI. Bài viết này sẽ tập trung vào sự kết hợp giữa hai công cụ này, minh họa cách tích hợp thông qua kịch bản kiểm thử “Đăng nhập vào GitHub và tạo Issue”. Dự án ví dụ sử dụng Maven làm công cụ quản lý.
Dưới đây là các phiên bản JDK, Maven và Serenity BDD được sử dụng trong dự án ví dụ:
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
Cấu trúc thư mục của dự án ví dụ như sau:
serenity-bdd-cucumber-integration-demo
├─ src/test
│ ├─ java
│ │ └─ com.example.tests
│ │ ├─ pages
│ │ │ ├─ LoginPage.java
│ │ │ └─ IssuesPage.java
│ │ ├─ stepdefs
│ │ │ ├─ LoginStep.java
│ │ │ └─ CreateIssueStep.java
│ │ ├─ utils
│ │ │ ├─ GoogleAuthenticatorUtil.java
│ │ │ └─ ConfigUtil.java
│ │ └─ CucumberTestSuite.java
│ └─ resources
│ ├─ features
│ │ └─ github-issues.feature
│ ├─ serenity.conf
│ └─ config.properties
└─ pom.xml
Nhìn vào cấu trúc trên, chúng ta thấy dự án có ba gói chính là pages
, stepdefs
và utils
. Gói pages
chứa các lớp đối tượng trang web, gói stepdefs
chứa các định nghĩa bước (step definition), và gói utils
chứa các lớp tiện ích.
Lớp CucumberTestSuite
đóng vai trò là điểm khởi đầu cho quá trình thực thi kiểm thử của dự án.
Thư mục con resources
chứa các tệp đặc điểm (feature files) với cú pháp Gherkin, tệp cấu hình serenity.conf
cho phép cấu hình loại trình duyệt Selenium và chế độ khởi chạy, và tệp config.properties
lưu trữ địa chỉ kho GitHub, khóa đăng nhập và các thông tin khác.
Dự án ví dụ 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-cucumber</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.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>${junit-platform-suite.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit-platform-engine</artifactId>
<version>${cucumber-junit-platform-engine.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
Từ đoạn mã trên, chúng ta có thể thấy rằng dự án sử dụng module cốt lõi của Serenity (serenity-core
) và module tích hợp Serenity-Cucumber (serenity-cucumber
). Ngoài ra, nó cũng sử dụng gói googleauth
để sinh mã xác thực Google Authenticator, gói logback-classic
để in nhật ký, và các module liên quan đến JUnit 5 để thực thi bộ kiểm thử.
Dưới đây là các plugin được sử dụng trong dự án ví dụ:
<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>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<includes>
<include>**/*TestSuite.java</include>
</includes>
<parallel>classes</parallel>
<parallel>methods</parallel>
<useUnlimitedThreads>true</useUnlimitedThreads>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</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>
Plugin maven-compiler-plugin
được sử dụng để biên dịch dự án; plugin maven-failsafe-plugin
để thực thi bộ kiểm thử; và plugin serenity-maven-plugin
để tạo báo cáo kiểm thử.
2. Phân tích các tập tin và mã nguồn chính
2.1 Tập tin đặc điểm (Feature File)
Tập tin đặc điểm của Cucumber sử dụng cú pháp Gherkin để miêu tả, mỗi tập tin đặc điểm có thể chứa nhiều kịch bản liên quan (Scenario). Trong một kịch bản, Given, When và Then được sử dụng để lần lượt đặt điều kiện ban đầu, thực hiện thao tác và khẳng định kết quả.
Nội dung tập tin đặc điểm github-issues.feature
được sử dụng để kiểm thử chức năng Issue của GitHub như sau:
# resources/features/github-issues.feature
Feature: Kiểm thử giao diện người dùng (UI) của GitHub Issues
Scenario: Thêm một Issue mới
Given Đăng nhập vào GitHub
When Mở trang Issues và thêm một Issue có tiêu đề "Serenity Cucumber Integration UI Test"
Then Issue được tạo thành công và có tiêu đề "Serenity Cucumber Integration UI Test"
2.2 Lớp đối tượng trang (Page Object Class)
Dự án này sử dụng mẫu thiết kế trang đối tượng (Page Object Model) phổ biến trong kiểm thử giao diện web. Các lớp liên quan đến đối tượng trang được đặt trong gói pages
, trong đó LoginPage
đại diện cho trang đăng nhập và IssuesPage
đại diện cho trang Issues.
Nội dung lớp LoginPage
như sau:
// src/test/java/com/example/tests/pages/LoginPage.javapackagecom.example.tests.pages;importcom.example.tests.utils.ConfigUtil;importcom.example.tests.utils.GoogleAuthenticatorUtil;importnet.thucydides.core.pages.PageObject;importorg.openqa.selenium.By;publicclass LoginPageextendsPageObject{privatestaticfinalStringLOGIN_URL=" mở đường dẫn đăng nhập openUrl(LOGIN_URL);// nhập tên người dùng và mật khẩu$(USERNAME_ELEM).sendKeys(ConfigUtil.getProperty("GITHUB_USERNAME"));$(PASSWORD_ELEM).sendKeys(ConfigUtil.getProperty("GITHUB_PASSWORD"));// nhấp nút "Sign in"$(SIGN_IN_BUTTON).click();// nhập mã xác thựcintcode=GoogleAuthenticatorUtil.getTotpCode(ConfigUtil.getProperty("GITHUB_TOTP_SECRET"));$(TOTP_ELEM).sendKeys(""+code);}}
Lớp này kế thừa từ lớp new88 game new889 PageObject
của Serenity, giúp dễ dàng sử dụng các thành phần thao tác giao diện như Selenium WebDriver. Ngoài ra, lớp này tuân theo yêu cầu của mô hình đối tượng trang, định nghĩa các vị trí phần tử trang dưới dạng thuộc tính và hành vi của trang dưới dạng phương thức (ví dụ: gọi phương thức login()
để đăng nhập vào GitHub).
Nội dung lớp IssuesPage
như sau:
// src/test/java/com/example/tests/pages/IssuesPage.javapackagecom.example.tests.pages;importcom.example.tests.utils.ConfigUtil;importnet.thucydides.core.pages.PageObject;importorg.openqa.selenium.By;publicclass IssuesPageextendsPageObject{privatestaticfinalStringISSUES_URL="/issues";privatestaticfinalByCREATE_ISSUE_BUTTON=By.partialLinkText("New issue");privatestaticfinalByINPUT_TITLE_ELEM=By.xpath("//input[@id='issue_title']");privatestaticfinalBySUBMIT_BUTTON=By.xpath("//button[contains(text(), 'Submit new issue')]");publicvoidcreateIssue(Stringtitle){// mở đường dẫn tạo IssueopenUrl(ConfigUtil.getProperty("GITHUB_REPO_URL")+ISSUES_URL);// nhấp nút "New issue"$(CREATE_ISSUE_BUTTON).click();// nhập tiêu đề Issue$(INPUT_TITLE_ELEM).sendKeys(title);// nhấp nút "Submit new issue"$(SUBMIT_BUTTON).click();}}
Lớp này cũng kế thừa từ lớp PageObject
của Serenity, cung cấp phương thức createIssue()
để tạo Issue.
tải winvn.vip 2.3 Lớp Định Nghĩa Bước (Step Definition Class)
Các lớp định nghĩa bước nằm trong gói stepdefs
, là các lớp “keo dán” liên kết với tập tin đặc điểm.
Phần thực hiện Given
trong tập tin github-issues.feature
được đặt trong lớp LoginStep
:
// src/test/java/com/example/tests/stepdefs/LoginStep.javapackagecom.example.tests.stepdefs;importcom.example.tests.pages.LoginPage;importio.cucumber.java.en.Given;publicclass LoginStep{privateLoginPageloginPage;@Given("Đăng nhập vào GitHub")publicvoidlogin(){loginPage.login();}}
Lớp này rất đơn giản, trực tiếp gọi phương thức loginPage
để thực hiện đăng nhập vào GitHub.
Phần thực hiện When
và Then
trong tập tin github-issues.feature
được đặt trong lớp CreateIssueStep
:
// src/test/java/com/example/tests/stepdefs/CreateIssueStep.javapackagecom.example.tests.stepdefs;importcom.example.tests.pages.IssuesPage;importio.cucumber.java.en.Then;importio.cucumber.java.en.When;import staticorg.hamcrest.CoreMatchers.startsWith;import staticorg.hamcrest.MatcherAssert.assertThat;publicclass CreateIssueStep{privateIssuesPageissuesPage;@When("Mở trang Issues và thêm một Issue có tiêu đề {string}")publicvoidcreateIssue(Stringtitle){// tạo IssueissuesPage.createIssue(title);}@Then("Issue được tạo thành công và có tiêu đề {string}")publicvoidcheckTitle(Stringtitle){assertThat(issuesPage.getTitle(),startsWith(title));}}
Lớp này gọi issuesPage
để tạo Issue và thực hiện khẳng định kết quả.
2.4 Lớp Điểm Nhập (Entry Class)
Việc thực thi dự án kiểm thử sử dụng khung kiểm thử đơn vị JUnit 5.
Nội dung lớp điểm nhập CucumberTestSuite
như sau:
// src/test/java/com/example/tests/CucumberTestSuite.javapackagecom.example.tests;importorg.junit.platform.suite.api.ConfigurationParameter;importorg.junit.platform.suite.api.IncludeEngines;importorg.junit.platform.suite.api.SelectClasspathResource;importorg.junit.platform.suite.api.Suite;import staticio.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME;@Suite@IncludeEngines("cucumber")@SelectClasspathResource("/features")@ConfigurationParameter(key=PLUGIN_PROPERTY_NAME,value="io.cucumber.core.plugin.SerenityReporterParallel,pretty,timeline:build/test-results/timeline")publicclass CucumberTestSuite{}
Lớp này sử dụng các chú thích liên quan đến JUnit 5 để đánh dấu, chỉ định máy phát động (engine), vị trí tài nguyên, và plugin tạo báo cáo song song.
Ngoài các lớp mã nguồn hoặc tệp cấu hình chính, còn có gói utils
với hai lớp GoogleAuthenticatorUtil
và ConfigUtil
, lần lượt dùng để sinh mã xác thực Google Authenticator và đọc tệp cấu hình resources/config.properties
.
3. Thực thi Trường Hợp Kiểm Thử Và Xem Báo Cáo
Vì dự án chạy bằng trình duyệt Chrome, hãy đảm bảo đã cài đặt phiên bản ChromeDriver mới nhất trước khi chạy.
Bạn có thể chạy lớp CucumberTestSuite
từ dòng lệnh bằng lệnh sau:
mvn clean verify
Sau khi chạy xong, báo cáo HTML sẽ được tạo trong thư mục target/site/serenity
. Khi mở báo cáo, bạn sẽ thấy hiệu ứng như sau:
![Báo cáo HTML được tạo bởi Serenity]
Trong báo cáo, mỗi bước của tập tin đặc điểm cùng với chi tiết (kết quả thực thi và ảnh chụp màn hình) đều được hiển thị.
4. Kết luận
Như vậy, bài viết này đã minh họa cách tích hợp Serenity BDD và Cucumber thông qua kịch bản kiểm thử “Đăng nhập vào GitHub và tạo Issue”. Dự án ví dụ hoàn chỉnh đã được đẩy lên GitHub, mời bạn quan tâm hoặc Fork.
[1] Serenity BDD: Getting Started With Cucumber using Serenity BDD and Screenplay -
#Kiểm thử tự động #Java #Cucumber