jck28-lucio-【实战】宠物商店接口自动化测试实战-l2

目录

  • 被测产品
  • 需求说明
  • 相关知识点
  • 接口自动化测试实战

被测产品

PetStore 宠物商城:

  • 一个在线的小型的商城。
  • 主要提供了增删查改等操作接口。
  • 结合 Swagger 实现了接口的管理

需求说明

  • 完成宠物商城宠物管理功能接口自动化测试。
    • 编写自动化测试脚本。
    • 完成复杂断言。

相关知识点

形式 章节 描述
知识点 代理配置 利用代理分析测试脚本,排查请求错误
知识点 多层嵌套响应断言 利用 jsonpath 进行多层嵌套的响应断言

实战思路

@startmindmap
scale 10

  • 实战思路
    ** 需求分析
    ** 接口测试用例设计
    ** 编写接口自动化测试脚本
    *** 脚本优化-配置代理查看接口数据
    *** 脚本优化-添加日志
    *** 脚本优化-使用 jsonpath 断言
    ** 生成测试报告
    @endmindmap

需求分析

  • 被测产品:宠物商店系统 - 宠物管理。
  • 宠物商店接口文档:https://petstore.swagger.io/
  • 宠物管理业务场景:
    • 添加宠物。
    • 查询宠物信息。
    • 修改宠物信息。
    • 删除宠物。

scale 10
autonumber
participant 测试人员 as tester
participant 宠物管理模块 as pet
participant 宠物商店 as petStore

tester → pet: 编写脚本
pet → petStore: 添加宠物
pet → petStore: 查询添加后宠物
customer → tester: 测试断言
pet → petStore: 修改宠物信息
pet → petStore: 查询添加后宠物
customer → tester: 测试断言
pet → petStore: 删除宠物
pet → petStore: 查询添加后宠物
customer → tester: 测试断言

宠物管理接口业务流程测试用例

编写自动化测试脚本思路

@startmindmap
scale 10

  • 思路
    ** 获取接口信息
    *** swagger 接口文档
    *** 前端抓包
    ** 单步调通接口
    ** 根据业务流程串联起来
    ** 添加断言,确认流程正常
    @endmindmap

脚本优化 - 配置代理查看接口数据

  • 在脚本中配置代理。
  • 抓包查看接口测试中的接口请求和响应数据。

// beforeAll定义一个代理的配置信息
RestAssured.proxy = host(“127.0.0.1”).withPort(8888);

given().relaxedHTTPSValidation() // 忽略HTTPS校验

执行顺序

  • junit5配置文件。

#声明测试方法的排序规则
junit.jupiter.testmethod.order.default=
org.junit.jupiter.api.MethodOrderer$OrderAnnotation

生成测试报告

<!-- allure报告 -->
        <allure.version>2.21.0</allure.version>
        <aspectj.version>1.9.19</aspectj.version>
        <allure.maven.version>2.12.0</allure.maven.version>
        <allure.cmd.download.url>
  https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline
        </allure.cmd.download.url>



<!--        allure报告-->
        <dependency>
  <groupId>io.qameta.allure</groupId>
  <artifactId>allure-junit5</artifactId>
  <version>${allure.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>${aspectj.version}</version>
        </dependency>


<!--        allure报告-->
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven-surefire-plugin.version}</version>
        <configuration>
  <argLine>
      -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
  </argLine>
        </configuration>

        <plugin>
  <groupId>io.qameta.allure</groupId>
  <artifactId>allure-maven</artifactId>
  <version>${allure.maven.version}</version>
  <configuration>
      <reportVersion>${allure.version}</reportVersion>
      <allureDownloadUrl>${allure.cmd.download.url}/${allure.version}/allure-commandline-${allure.version}.zip</allureDownloadUrl>
  </configuration>
        </plugin>
package com.restassured.petstore;

import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.List;

import static io.restassured.RestAssured.given;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.everyItem;
import static org.junit.jupiter.api.Assertions.*;

public class PetTest {
    static String baseUrl;
    static String petId;
    static String newPetName;
    static String updatePetName;

    @BeforeAll
    public static void beforeAll() {
        baseUrl = "https://petstore.swagger.io/v2/pet";
        petId = "1234567891234567890";
        newPetName = "newPet";
        updatePetName = "updatePet";
        RestAssured.useRelaxedHTTPSValidation();

    }

    //添加宠护测试用例
    @Test
    @Order(100)
    public void addTest() {
        add();
        String body = query();
        DocumentContext context = JsonPath.parse(body);
        List<Long> ids = context.read("$..id"); //$[*]..id
        System.out.println("ids:" + ids);
        System.out.println("petId:" + Long.valueOf(petId));
        List<String> names = context.read("$..name");//$[*]..name
        System.out.println("names:" + names);
        System.out.println("newPetName:" + newPetName);
        List<String> status = context.read("$..status");//$[*]..status
        System.out.println("status:" + status);
        assertAll(
                ()->assertThat(status,everyItem(equalTo("avlilable"))),//匹配所有集合都有avlilable
                () -> assertThat(ids, Matchers.hasItem(Long.valueOf(petId))),//匹配单个集合中有petId
                () -> assertThat(names, Matchers.hasItem(newPetName))//匹配单个集合中有newPetName
        );
    }




    //新增
    //https://petstore.swagger.io/v2/pet
    //jsonviewer.stack.hu
//    @Test
    public void add() {
        String addPet = "{\"id\":" + petId + ",\"category\":{\"id\":0,\"name\":\"宠物狗\"},\"name\":\"" + newPetName + "\",\"photoUrls\":[\"newstring\"],\"tags\":[{\"id\":0,\"name\":\"string\"}],\"status\":\"available\"}";
        given()
                .contentType(ContentType.JSON)
                .body(addPet)
                .when()
                .post(baseUrl)
                .then()
                .log().all();
    }

//    @Test
    public void add1() {
        String addPet = "{\"id\":" + petId + ",\"category\":{\"id\":0,\"name\":\"宠物狗\"},\"name\":\"" + newPetName + "\",\"photoUrls\":[\"newstring\"],\"tags\":[{\"id\":0,\"name\":\"string\"}],\"status\":\"available\"}";
        given()
                .contentType(ContentType.JSON)
                .body(addPet)
                .when()
                .post(baseUrl)
                .then()
                .log().all();
    }

    //查看
    //https://petstore.swagger.io/v2/pet/findByStatus?status=available
    //https://petstore.swagger.io/v2/pet/findByStatus?status=available
//    @Test
    public String query() {
        HashMap<String, Object> statusQuery = new HashMap<>() {{
            put("status", "available");
        }};

        String body = given().log().all()
                .queryParams(statusQuery)
                .when()
                .get(baseUrl + "/findByStatus")
                .then()
                .log().all()
                .extract().response().getBody().asString();
        System.out.println(body);
        return body;
    }

//    @Test
    public void query1() {
        HashMap<String, Object> statusQuery = new HashMap<>() {{
            put("status", "available");
        }};

        String body = given().log().all()
                .queryParams(statusQuery)
                .when()
                .get(baseUrl + "/findByStatus")
                .then()
                .log().all()
                .extract().response().getBody().asString();
        System.out.println(body);
        DocumentContext context = JsonPath.parse(body);

        List<Long> ids = context.read("$..id");
        System.out.println("ids:" + ids);
        List<String> names = context.read("$..name");
        System.out.println("names:" + names);
    }

    //更新
    //https://petstore.swagger.io/v2/pet
    //更新宠护测试用例
    @Test
    @Order(150)
    public void updateTest() {
        update();
        String body = query();
        DocumentContext context = JsonPath.parse(body);
        List<Long> ids = context.read("$..id");
        System.out.println("ids:" + ids);
        System.out.println("petId:" + Long.valueOf(petId));
        List<String> names = context.read("$..name");
        System.out.println("names:" + names);
        System.out.println("updatePetName:" + updatePetName);
        assertAll(
                () -> assertThat(ids, Matchers.hasItem(Long.valueOf(petId))),
                () -> assertThat(names, Matchers.hasItem(updatePetName))
        );
    }

    public void update() {
        String updatePet = "{\"id\":" + petId + ",\"category\":{\"id\":0,\"name\":\"宠物狗\"},\"name\":\"" + updatePetName + "\",\"photoUrls\":[\"updatestring\"],\"tags\":[{\"id\":0,\"name\":\"string\"}],\"status\":\"available\"}";
        given()
                .contentType(ContentType.JSON)
                .body(updatePet)
                .when()
                .put(baseUrl)
                .then()
                .log().all();
    }



//    @Test
    public void update1() {
        String updatePet = "{\"id\":" + petId + ",\"category\":{\"id\":0,\"name\":\"宠物狗\"},\"name\":\"" + updatePetName + "\",\"photoUrls\":[\"updatestring\"],\"tags\":[{\"id\":0,\"name\":\"string\"}],\"status\":\"available\"}";
        given()
                .contentType(ContentType.JSON)
                .body(updatePet)
                .when()
                .put(baseUrl)
                .then()
                .log().all();
    }

    //删除
    //https://petstore.swagger.io/v2/pet/Pet id
    //更新宠护测试用例
    @Test
    @Order(200)
    public void deleteTest() {
        delete();
        String body = query();
        DocumentContext context = JsonPath.parse(body);
        List<Long> ids = context.read("$..id");
        System.out.println("ids:" + ids);
        System.out.println("petId:" + Long.valueOf(petId));
        List<String> names = context.read("$..name");
        assertAll(
                () -> assertThat(ids, Matchers.not(Matchers.hasItem(Long.valueOf(petId))))
        );
    }

    public void delete() {
        String body = "{\"id\":1234567890,\"category\":{\"id\":0,\"name\":\"宠物狗\"},\"name\":\"doggie\",\"photoUrls\":[\"updatestring\"],\"tags\":[{\"id\":0,\"name\":\"string\"}],\"status\":\"available\"}";
        given()
                .when()
                .delete(baseUrl + "/" + petId)
                .then()
                .log().all();
    }

//    @Test
    public void delete1() {
        String body = "{\"id\":1234567890,\"category\":{\"id\":0,\"name\":\"宠物狗\"},\"name\":\"doggie\",\"photoUrls\":[\"updatestring\"],\"tags\":[{\"id\":0,\"name\":\"string\"}],\"status\":\"available\"}";
        given()
                .when()
                .delete(baseUrl + "/" + petId)
                .then()
                .log().all();
    }

}

总结

通过 Swagger 文档获取接口信息。
使用 given-when-then 发出携带请求参数的 GET 请求。
多断言响应符合是否符合预期。
添加代理,抓包查看接口请求和响应数据。
使用 Jsonpath 提取复杂结构响应数据,然后进行断言。
生成 Allure 测试报告。

源码地址

gitlab.stuq.ceshiren.com

遇到问题:

1、id设置为"1234567890",查询获取所有id代码
List ids = context.read(“$…id”);
断言 () → assertThat(ids, Matchers.hasItem(Long.valueOf(petId)))

报错:类型不匹配

解决办法:

Id写长一点就好了(1234567891234567890),我把刚才的1234567890转换成Integer类型也是ok的,类型转换为问题