人工智能(AI)已经改变了自动化Rest API测试的设计和执行方式。通过应用机器学习(ML)和自然语言处理技术,AI可以分析庞大的数据集和API规范,自动生成全面且相关的测试用例。这加快了测试过程,并通过识别未被探索的质量领域来提高测试的有效性。
在本文中,您将学习如何使用StackSpot AI的情境化代码助手来创建自动化Rest API测试,从而简化自动化项目的开发和编码。
了解StackSpot AI
StackSpot是一个开发平台,它通过集中和重用技术标准、通过AI生成高度情境化的代码,使工程团队能够快速实现系统并更快地交付价值。它分为三个产品:StackSpot EDP、StackSpot云服务和StackSpot AI(后者是本文的重点)。
StackSpot AI可以根据您的上下文、知识来源和技术决策来生成更果断、高质量的建议。此外,AI助手还能够创建快速命令来自动化重复性任务。告别通用建议,采用超情境化的代码生成!
最好的部分是:StackSpot AI提供了一项免费+增值服务的计划。您可以使用网页版或下载IDE扩展(IntelliJ或Visual Code)来开始使用!
自动化Rest API测试:使用StackSpot AI的第一步
在本文中,我们将使用Java、Rest Assured、Cucumber和Maven创建一个Rest API自动化测试项目。
我们将使用个人账号(GitHub)登录StackSpot AI门户,下载AI情境化代码助手插件,并添加开发工具(IntelliJ)。
AI情境化代码向导将根据问题和上下文帮助生成初始项目代码,并建议添加到项目中的代码。
最后,我们将添加新的测试场景并重构代码,使我们的项目对软件社区来说更加全面且可重用。
那么,让我们开始吧:
登录StackSpot AI登录页面。这一步需要先在GitHub上创建一个账号。
在StackSpot AI环境中,您将会看到这个初始屏幕:
安装步骤
为了进行安装,请遵循以下推荐的自动化测试构建指南:
集成开发环境(IDE)
- IntelliJ(版本2024.1 / 241.14494.240)
IDE插件
- StackSpot AI(版本1.5.4)
- Cucumber-Java(版本241.14494.158)
- Gherkin(版本241.14494.150)
编程语言
- Java(版本11.0.20 / 2023年7月18日发布的长期支持版本)
依赖项
- Maven(版本3.9.5)
Maven库
- Rest Assured(版本4.3.3)
- Cucumber-Java(版本6.10.4)
- Cucumber-JUnit(版本6.10.4)
- JUnit(版本4.13.2)
- JavaFaker(版本1.02)
请按照上述工具和版本号进行安装,以确保自动化测试项目的顺利构建和运行。
创建自动化Rest API测试项目
要创建并运行Rest API自动化测试项目,请遵循以下指南。
1 – 为自动化Rest API测试创建一个新项目
在完成安装(上一步)后,只需:
- 打开IntelliJ IDE。
- 转到“File”菜单并选择“New -> Project”。
- 点击“New Project”并选择“Java”选项。
- 在“Name”字段中输入项目的名称。
- 点击“Build System”并选择“Maven”。
就这样!Rest API自动化测试项目已经创建完成。
2 – 使用StackSpot AI进行身份验证
在IntelliJ IDE已经打开且项目已经创建(上一步)的情况下,只需:
- 进入StackSpot AI插件。
- 在GitHub账号的电子邮件字段中填写信息。
- 点击“Continue with GitHub(使用GitHub继续)”按钮。
- 在弹出的屏幕中点击“Yes”按钮。收到确认后,返回IntelliJ。
就这样!身份验证完成后,您就可以使用StackSpot AI了。
3 – 生成代码
在IntelliJ IDE中已经创建了项目并且已经登录到StackSpot AI(上一步)之后,只需:
- 进入StackSpot AI插件。
- 向AI提问:使用Java 11、Maven、Rest Assured和Cucumber生成一个Rest API POST测试的示例。在本文中,您学习如何在StackSpot AI中创建一个好的提示。
- 复制生成的代码,并为项目创建建议的文件夹/文件。
就这样!代码已经生成,我们可以将其添加到创建的项目中以供使用。
将StackSpot AI生成的代码添加到项目中
让我们按照以下步骤将生成的代码添加到自动化Rest API测试项目中:
-
使用Maven配置项目
在项目的pom.xml文件中,为Cucumber、JUnit和RestAssured添加以下依赖项。
pom.xml
<dependencies>
<!-- RestAssured -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>4.3.3</version>
<scope>test</scope>
</dependency>
<!-- Cucumber -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>6.10.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>6.10.4</version>
<scope>test</scope>
</dependency>
<!-- JUnit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
-
使用Cucumber创建测试场景
为Cucumber创建一个功能文件。
src/test/resources/features/postFeature.feature
Feature: Test POST API endpoint
Scenario: Post new data to the API
Given I set POST API endpoint
When I send POST HTTP request
Then I receive valid HTTP response code 201
-
使用RestAssured实现测试
现在,使用RestAssured实现测试步骤。为您的Cucumber场景创建一个对应的测试类。
src/test/java/stepDefinitions/PostApiSteps.java
package com.example.steps;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import static org.junit.Assert.*;
public class PostApiSteps {
private Response response;
@Given("I set POST API endpoint")
public void i_set_post_api_endpoint() {
RestAssured.baseURI = "http://yourapi.com/api";
}
@When("I send POST HTTP request")
public void i_send_post_http_request() {
response = RestAssured.given().contentType("application/json")
.body("{\"key\": \"value\"}")
.when().post("/endpoint");
}
@Then("I receive valid HTTP response code 201")
public void i_receive_valid_http_response_code_201() {
assertEquals(201, response.getStatusCode());
}
}
-
使用Cucumber设置运行器
创建一个类来运行Cucumber测试。
src/test/java/cucumberOptions/TestRunner.java
package com.example;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(
features = "src/test/resources/features",
glue = "com.example.steps",
plugin = {"pretty", "html:target/cucumber-reports.html"},
monochrome = true
)
public class TestRunner {
}
运行自动化Rest API测试
要运行自动化Rest API测试,您可以使用Maven命令。
mvn test
此时,您已经拥有了一个集成Rest API自动化测试项目的代码和结构的示例,该项目会发出POST请求,接收响应,并验证状态码。现在,您可以根据需要调整已生成的内容。
接下来,我们需要改进代码并整理项目,添加GET请求,接收响应,并验证数据。
为此,请使用ServeRest API来:
- 注册新用户(POST User)
- 查询已注册用户(GET User)
- 查询未注册用户(尝试GET不存在的User)
以下将基于要验证的场景展示所做的调整。
重构项目以使实现更加简洁和组织有序
为了进行重构,请进行以下更改:
1 – 使用Maven调整项目
调整pom.xml文件以包含实现所需的依赖项。
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>org.example</groupId>
<artifactId>StackSpot-api-integration-tests</artifactId>
<version>1.0-SNAPSHOT</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>
<!-- RestAssured -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>4.3.3</version>
<scope>test</scope>
</dependency>
<!-- Cucumber -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>6.10.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>6.10.4</version>
<scope>test</scope>
</dependency>
<!-- JUnit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- Java Faker -->
<dependency>
<groupId>com.GitHub.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
</project>
2 – 使用Cucumber调整测试场景
调整resources/features/user.feature文件,以包含实现所需的测试场景。
src/test/resources/features/user.feature
Feature: User API
@all @user-register
Scenario: Should register a new user
Given I have the data to register a new user
When I make a POST request to the URL "https://serverest.dev/usuarios"
Then The response status code should be 201 to a new user
@all @user-not-registered
Scenario: Should query registered user
Given I do not have a registered user but wish to register
When I make a GET request to the URL "https://serverest.dev/usuarios"
Then The response status code should be 200 to registered user
@all @user-non-existent
Scenario: Should query non-registered user
Given I do not have a registered user "XPTO"
When I make a GET request to the URL "https://serverest.dev/usuarios"
Then The response status code should be 400 to non-registered user
3 – 使用RestAssured调整测试步骤
调整stepDefinitions/UserSteps.java文件,以包含用于注册新用户、查询已注册用户和查询未注册用户的特性测试的实现。
src/test/java/stepDefinitions/UserSteps.java
package stepDefinitions;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import io.restassured.response.Response;
import services.UserService;
public class UserSteps {
private Response response;
private String body;
private String idUser;
private final UserService userService = new UserService();
@Given("I have the data to register a new user")
public void i_have_the_data_to_register_a_new_user() {
body = userService.generateUserData();
}
@When("I make a POST request to the URL {string}")
public void i_make_a_post_request_to_the_url(String url) {
response = userService.createNewUser(url, body);
}
@Then("The response status code should be {int} to a new user")
public void the_response_status_code_should_be_to_a_new_user(int statusCode) {
idUser = userService.validateRegisteredUserData(response, statusCode);
}
@Given("I do not have a registered user but wish to register")
public void i_do_not_have_a_registered_user_but_wish_to_register() {
idUser = userService.checkExistingUser(null);
}
@When("I make a GET request to the URL {string}")
public void i_make_a_get_request_to_the_url(String url) {
response = userService.queryUser(url, idUser);
}
@Then("The response status code should be {int} to registered user")
public void the_response_status_code_should_be_to_registered_user(int statusCode) {
userService.validateQueriedUserData(response, idUser, statusCode);
}
@Given("I do not have a registered user {string}")
public void i_do_not_have_a_registered_user(String newUserId) {
idUser = newUserId;
}
@When("I make an attempt to GET request to the URL {string}")
public void i_make_an_attempt_to_get_request_to_the_url(String url) {
response = userService.queryUser(url, idUser);
}
@Then("The response status code should be {int} to non-registered user")
public void the_response_status_code_should_be_to_non_registered_user(int statusCode) {
userService.validateNonRegisteredUserData(response, statusCode);
}
}
4 – 创建DTO结构以操作请求数据
创建dto/UserDto文件,用于创建get/set方法以及访问对象/类的属性。
src/test/java/dto/UserDto.java
package dto;
public class UserDto {
private String name;
private String email;
private String password;
private String admin;
// Getter and Setter for name
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// Getter and Setter for email
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
// Getter and Setter for password
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
// Getter and Setter for admin
public String getAdmin() {
return admin;
}
public void setAdmin(String admin) {
this.admin = admin;
}
}
5 – 创建Service结构以设置请求
创建service/UserService.java文件,用于设置要发出的请求。
src/test/java/service/UserService.java
package services;
import com.github.javafaker.Faker;
import dto.UserDto;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;
import static io.restassured.RestAssured.given;
import static org.junit.Assert.assertEquals;
public class UserService {
private Response response;
private String requestBody;
private String userId;
private UserDto userDto;
private Faker faker;
private String newUserId;
public String generateUserData(){
faker = new Faker();
userDto = new UserDto();
userDto.setName(faker.name().name());
userDto.setEmail(faker.internet().emailAddress());
userDto.setPassword("123456");
userDto.setAdmin("true");
requestBody = "{\n" +
" \"nome\": \""+userDto.getName()+"\",\n" +
" \"email\": \""+userDto.getEmail()+"\",\n" +
" \"password\": \""+ userDto.getPassword()+"\",\n" +
" \"administrador\": \""+ userDto.getAdmin()+"\"\n" +
"}";
return requestBody;
}
public Response createNewUser(String url, String requestBody){
response = given()
.header("Content-type", "application/json")
.and()
.log().all()
.body(requestBody)
.when()
.post(url)
.then()
.log().all()
.extract().response();
return response;
}
public String validateRegisteredUserData(Response response, int statusCode){
JsonPath jsonPathEvaluator = response.jsonPath();
assertEquals(statusCode, response.getStatusCode());
userId = jsonPathEvaluator.get("_id");
return userId;
}
public String checkExistingUser(String userId){
String newBody;
Response newResponse;
if (userId == null){
newBody = generateUserData();
newResponse = createNewUser("https://serverest.dev/usuarios",newBody);
newUserId = validateRegisteredUserData(newResponse, 201);
}
else{
newUserId = userId;
}
return newUserId;
}
public Response queryUser(String url, String newUserId){
response = given()
.header("Content-type", "application/json")
.and()
.log().all()
.when()
.get(url + "/" + newUserId)
.then()
.log().all()
.extract().response();
return response;
}
public void validateQueriedUserData(Response response, String newId, int statusCode){
JsonPath jsonPathEvaluator = response.jsonPath();
if (newUserId.equals(newId)) {
assertEquals(statusCode, response.getStatusCode());
assertEquals(newUserId, jsonPathEvaluator.get("_id"));
}
else {
assertEquals(userDto.getName(), jsonPathEvaluator.get("name"));
assertEquals(userDto.getEmail(), jsonPathEvaluator.get("email"));
assertEquals(userDto.getPassword(), jsonPathEvaluator.get("password"));
assertEquals(userDto.getAdmin(), jsonPathEvaluator.get("admin"));
assertEquals(statusCode, response.getStatusCode());
assertEquals(userId, jsonPathEvaluator.get("_id"));
}
}
public void validateNonRegisteredUserData(Response response, int statusCode){
assertEquals(statusCode, response.getStatusCode());
}
}
重构后运行测试
要运行测试,您可以使用Maven命令。
mvn test
就这样!调整后的项目已成功执行。在StackSpot AI的帮助下,场景编写更加高效,促进了代码重用,并简化了自动化Rest API测试。
结论
本文展示了在自动化Rest API测试过程中采用像StackSpot AI这样的情境化人工智能工具的优势。通过整合合适的人工智能工具,整个软件开发周期的速度和效率都得到了提升。在这个场景下,软件质量流程也从新功能中获得了重大收益。
借助StackSpot AI,我们可以根据自己的标准和知识来源采纳果断的建议。这为他们的自动化Rest API测试和QA流程带来了前所未有的效率、可靠性和创新。