Как протестировать проект Spring Boot с помощью ZeroCode?

Опубликовано: 22 Февраля, 2023

Среда автоматизированного тестирования Zerocode для концепции проекта REST API рассматривается в этом руководстве на примере проекта maven с весенней загрузкой. Давайте посмотрим на зависимости для Zerocode:

<dependency>
      <groupId>org.jsmart</groupId>
      <artifactId>zerocode-tdd</artifactId>
      <version>1.3.27</version>
      <scope>test</scope>
 </dependency>

Фреймворк Zerocode поддерживает следующие

  • ОТДЫХАТЬ
  • МЫЛО
  • Безопасность
  • Нагрузка/стресс
  • База данных
  • Апач Кафка
  • ГрафQL

В этом руководстве мы рассмотрим тестирование REST API.

Пример проекта

Структура проекта:

пом.xml

XML




<?xml version="1.0" encoding="UTF-8"?>
    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>com.gfg.zerocode</groupId>
    <artifactId>zerocode</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>${spring.boot.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jsmart</groupId>
            <artifactId>zerocode-tdd</artifactId>
            <version>${zerocode-tdd.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
  
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <profiles>
                        <profile>it</profile>
                    </profiles>
                </configuration>
                <executions>
                    <execution>
                        <id>pre-integration-test</id>
                        <goals>
                            <goal>start</goal>
                        </goals>
                        <configuration>
                            <skip>${skip.it}</skip>
                        </configuration>
                    </execution>
                    <execution>
                        <id>post-integration-test</id>
                        <goals>
                            <goal>stop</goal>
                        </goals>
                        <configuration>
                            <skip>${skip.it}</skip>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>${maven-failsafe-plugin.version}</version>
                <configuration>
                    <skip>${skip.it}</skip>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.maven.surefire</groupId>
                        <artifactId>surefire-junit47</artifactId>
                        <version>${surefire-junit47.version}</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
  
    <properties>
        <maven-failsafe-plugin.version>3.0.0-M5</maven-failsafe-plugin.version>
        <surefire-junit47.version>3.0.0-M5</surefire-junit47.version>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <spring.boot.version>2.4.2</spring.boot.version>
        <skip.it>true</skip.it>
        <zerocode-tdd.version>1.3.27</zerocode-tdd.version>
    </properties>
  
</project>

Чтобы протестировать REST API, давайте создадим образец приложения загрузки Spring. Давайте сначала создадим класс модели

GeekUser.java

Java




public class GeekUser {
    
    private String id;
    private String firstName;
    private String lastName;
    private String departmentName;
    
    public String getDepartmentName() {
        return departmentName;
    }
  
    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }
  
    public float getSalary() {
        return salary;
    }
  
    public void setSalary(float salary) {
        this.salary = salary;
    }
  
    private float salary;
  
    public String getId() {
        return id;
    }
  
    public void setId(String id) {
        this.id = id;
    }
  
    public String getFirstName() {
        return firstName;
    }
  
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
  
    public String getLastName() {
        return lastName;
    }
  
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

GeekUserZerocodeApplication.java

Java




import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
  
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
  
@SpringBootApplication
@RestController
@RequestMapping("/api/users")
public class GeekUserZerocodeApplication {
    private List<GeekUser> users = new ArrayList<>();
  
    public static void main(String[] args) {
        SpringApplication.run(GeekUserZerocodeApplication.class, args);
    }
  
    @PostMapping
    public ResponseEntity create(@RequestBody GeekUser user) {
        if (!StringUtils.hasText(user.getFirstName())) {
            return new ResponseEntity("firstName can"t be empty!", HttpStatus.BAD_REQUEST);
        }
        if (!StringUtils.hasText(user.getLastName())) {
            return new ResponseEntity("lastName can"t be empty!", HttpStatus.BAD_REQUEST);
        }
        if (!StringUtils.hasText(user.getDepartmentName())) {
            return new ResponseEntity("DeparmentName can"t be empty!", HttpStatus.BAD_REQUEST);
        }
        if (user.getSalary() < 0 ) {
            return new ResponseEntity("Salary is not valid!", HttpStatus.BAD_REQUEST);
        }
        user.setId(UUID.randomUUID()
            .toString());
        users.add(user);
        return new ResponseEntity(user, HttpStatus.CREATED);
    }
  
}

Мы должны написать сценарий для проверки того же

{
  "scenarioName": "geek test user creation endpoint",
  "steps": [  // Array of JSON objects, as much we want we can store
    {
      "name": "geek_test_successful_creation",
      "url": "/api/users", // Relative URL
      "method": "POST",
      "request": {
        "body": { // We have to specify whole bean class parameter and its values
          "firstName": "Rachel",
          "lastName": "Green",
          "departmentName":"IT",
          "salary":100000.0
        }
      },
      "verify": { // expected part containing status and body
        "status": 201, // status code for a given HTTP call
        "body": { // Resultant body from the call
          "id": "$NOT.NULL",
          "firstName": "Rachel",
          "lastName": "Green",
          "departmentName":"IT",
          "salary":100000.0
        }
      }
    }
}

Вышеприведенный вызов — это успешный вызов, создающий пользователя. Точно так же мы можем сделать и часть проверки

 {
      "name": "test_firstname_validation",
      "url": "/api/users",
      "method": "POST",
      "request": {
        "body": {
          "firstName": "",
          "lastName": "Bing",
          "departmentName":"IT",
          "salary":100000.0
        }
      },
      "assertions": {
        "status": 400,
        "rawBody": "firstName can"t be empty!"
      }
    },
    {
      "name": "test_lastname_validation",
      "url": "/api/users",
      "method": "POST",
      "request": {
        "body": {
          "firstName": "Monica",
          "lastName": "",
          "departmentName":"Chef",
          "salary":100000.0
        }
      },
      "assertions": {
        "status": 400,
        "rawBody": "lastName can"t be empty!"
      }
    },
   {
      "name": "test_departmentname_validation",
      "url": "/api/users",
      "method": "POST",
      "request": {
        "body": {
          "firstName": "Phoebe",
          "lastName": "Buffe",
          "departmentName":"",
          "salary":50000.0
        }
      },
      "assertions": {
        "status": 400,
        "rawBody": "DeparmentName can"t be empty!"
      }
    }

Мы можем объединить все вместе и хранить в папке test/resources. По сути, это файл JSON, объединяющий все проверяемые записи. Теперь переходим к части тестового файла

  • @RunWith(ZeroCodeUnitRunner.class) — ZeroCodeUnitRunner, так как за него отвечает
  • @TargetEnv — укажите файл свойств, необходимый для запуска сценария.

GeekUserEndpointIT.java

Java




import org.jsmart.zerocode.core.domain.Scenario;
import org.jsmart.zerocode.core.domain.TargetEnv;
import org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
  
// Here in RunWith it has been specified
// as ZeroCodeUnitRunner, as it is responsible
@RunWith(ZeroCodeUnitRunner.class)
// @TargetEnv – this points to the property file 
// that will be used when our scenario runs
@TargetEnv("rest_api.properties")
public class GeekUserEndpointIT {
  
    @Test
    @Scenario("rest/geek_user_create_test.json")
    public void test_geekuser_creation_endpoint() {
    }
  
}

rest_api.properties

web.application.endpoint.host=http://localhost # In case of changes they need to be modified appropriately
web.application.endpoint.port=8080
web.application.endpoint.context=

Для выполнения тестов в pom.xml добавляются необходимые зависимости

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>3.0.0-M5</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.maven.surefire</groupId>
            <artifactId>surefire-junit47</artifactId>
            <version>3.0.0-M5</version>
        </dependency>
    </dependencies>
    <executions>
        <execution>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Мы можем запустить проект в командной строке, используя

mvn verify -Dskip.it=false

В целевой папке каталога мы видим несколько файлов, которые помогают понять различные уровни тестирования.

Точно так же любые приведенные сценарии тестирования проверяются на соответствие Zerocode.