接口实战

霍格沃兹测试开发学社

ceshiren.com

目录

  • 接口
  • 产品需求分析
  • 测试用例设计思路
  • 接口自动化脚本编写

接口测试

  • 接口介绍
  • 接口分类
  • 接口测试

接口介绍

  • 输入 —> 处理 —> 输出

接口分类

  • 内部接口
  • 外部接口【相对于内部接口而存在的一个概念】

接口测试

接口测试

  • 模拟调用方「Client 端」,通过接口通信来检测被测接口的正确性和容错性

接口自动化测试

  • 自动化流程
  • 自动化对比
  • 测试策略
  • 工具选型
  • 接口自动化的时机

自动化流程

自动化对比

UI 自动化测试 接口自动化测试
成本 ⭐️⭐️⭐️ ⭐️
测试效率 ⭐️⭐️ ⭐️⭐️⭐️⭐️⭐️
用例编写效率 ⭐️⭐️ ⭐️⭐️⭐️⭐️⭐️
稳定性 ⭐️⭐️⭐️ ⭐️⭐️⭐️⭐️⭐️
自动化回归测试效率 ⭐️⭐️⭐️ ⭐️⭐️⭐️⭐️⭐️
测试覆盖度 ⭐️⭐️ ⭐️⭐️⭐️⭐️⭐️
自动生成用例成本 ⭐️⭐️ ⭐️⭐️⭐️⭐️⭐️

测试策略

  • 金字塔模型
  • 菱形模型

金字塔模型

菱形模型

工具选型

测试类型 工具 价值
接口抓包 CharlesFiddler 接口抓包工具,抓取 App 的数据包
接口测试 PostmanApiFox 接口调试工具,接口手工测试工具,学习成本低,直接安装即可使用
接口自动化测试 Java:HttpClientRestAssuredOkHttphttprunner4j
Python:requestshttprunner
用于接口自动化测试的 JavaPython第三方库,需要与对应编程语言结合使用
性能测试 JMeter 性能测试工具

价值

  • 接口自动化 投资收益比最高
  • 更早的发现问题
  • 更快的质量反馈

测试流程

  • 产品:需求评审
  • 研发:系统架构设计评审
  • 测试:测试用例评审
  • 测试:自动化脚本编写、优化
  • 测试:发送测试报告「
  • 测试:自动化脚本 CI/CD 持续集成

部门创建

  • 通过API创建树状部门结构
  • 部门名称
    • 同一个层级的部门名不能有重复
    • 长度限制:1~32个字符
    • 字符不能包括:*?"<>|
  • 部门排序规则
    • 在父部门中的次序值
    • order值大的排序靠前
    • 有效的值范围是[0, 2^32)

修改部门

  • 同一个层级名不能重复
  • 设置一个部门在父部门的次序值
  • 长度限制

获取部门

  • 部门id
    • 获取指定部门及其下的子部门
    • 不填,默认获取全量组织架构

成员创建

  • 成员ID
    • 企业内必须唯一
    • 长度为1~64个字节
    • 只能 数字、字母和“_-@.”四种字符组成
      • 第一个字符必须是数字或字母
    • 唯一性检查时会忽略大小写
  • 名称
    • 长度为1~64个utf8字符

问题发现模型

系统交互

系统交互

系统交互

  • 新需求是否有侵入性
  • 改动必要性

接口自动化测试流程

  • 获取接口相关信息
  • 接口测试用例设计
  • 接口测试框架选择
  • 测试用例编写与维护
  • 持续集成

1.获取接口相关信息

  • 获取路径
    • 开发的接口文档、swagger地址、自己抓包
  • 获取内容
    • 请求
      • url 、请求头、请求体
    • 返回
      • 状态码、返回头、返回体

2.设计接口测试用例

  • 等价类边界值
    • 参数: null、“”
  • 参数组合
  • 多个非必填参数,作为整体进行设计

3.接口测试框架选择

rest-assured

4.发送请求

  • 三剑客:given,when,then

pom



    <properties>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <!-- 使用 Java 11 语言特性 ( -source 11 ) 并且还希望编译后的类与 JVM 11 ( -target 11 )兼容,
        可以添加以下两个属性,它们是默认属性插件参数的名称 -->
        <java.version>11</java.version>
        <!-- 对应junit Jupiter的版本号;放在这里就不需要在每个依赖里面写版本号,导致对应版本号会冲突 -->
        <junit.jupiter.version>5.8.2</junit.jupiter.version>
        <!-- maven-plugins -->
        <maven.compiler.version>3.8.1</maven.compiler.version>
        <maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
        <!-- 断言 -->
        <hamcrest.version>2.2</hamcrest.version>
        <!-- log日志 -->
        <slf4j.version>2.0.0-alpha7</slf4j.version>
        <logback.version>1.3.0-alpha16</logback.version>
        <!-- allure报告 -->
        <allure.version>2.18.1</allure.version>
        <aspectj.version>1.9.9.1</aspectj.version>
        <allure-maven.version>2.10.0</allure-maven.version>
        <allure.cmd.download.url>
            https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline
        </allure.cmd.download.url>
        <!-- faker -->
        <javafaker.version>1.0.2</javafaker.version>
        <!-- selenium -->
        <selenium.version>4.3.0</selenium.version>
        <!-- appium -->
        <appium.version>8.1.1</appium.version>
        <!-- rest-assured -->
        <rest-assured.version>5.1.1</rest-assured.version>
        <!-- fasterjson -->
        <jackson.version>2.13.1</jackson.version>
        <!-- apache-commonio -->
        <commonio.version>2.11.0</commonio.version>
    </properties>
    <!--    物料清单 (BOM)-->
    <dependencyManagement>
        <dependencies>
            <!--当使用 Gradle 或 Maven 引用多个 JUnit 工件时,此物料清单 POM 可用于简化依赖项管理。不再需要在添加依赖时设置版本-->
            <dependency>
                <groupId>org.junit</groupId>
                <artifactId>junit-bom</artifactId>
                <version>${junit.jupiter.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>31.0.1-jre</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <repositories>
        <repository>
            <id>jitpack.io</id>
            <url>https://jitpack.io</url>
        </repository>
    </repositories>

    <dependencies>
        <!--junit5-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <!--对应添加的依赖的作用范围-->
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-suite</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
            <scope>test</scope>
        </dependency>
        <!--hamcrest断言-->
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest</artifactId>
            <version>${hamcrest.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
            <version>${hamcrest.version}</version>
            <scope>test</scope>
        </dependency>
        <!--faster json解析yaml文件 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-yaml</artifactId>
            <version>${jackson.version}</version>
            <scope>compile</scope>
        </dependency>
        <!--        csv文件解析-->
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-csv</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <!-- log日志 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>

        <!-- common io-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>${commonio.version}</version>
        </dependency>
        <!-- allure-->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-junit5</artifactId>
            <version>${allure.version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
            <scope>runtime</scope>
        </dependency>
        <!--  随机测试数据生成库  -->
        <dependency>
            <groupId>com.github.javafaker</groupId>
            <artifactId>javafaker</artifactId>
            <version>${javafaker.version}</version>
        </dependency>
        <!-- selenium-->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>${selenium.version}</version>
            <scope>compile</scope>
        </dependency>
        <!-- appium -->
        <dependency>
            <groupId>io.appium</groupId>
            <artifactId>java-client</artifactId>
            <version>${appium.version}</version>
            <scope>compile</scope>
        </dependency>
        <!-- rest-assured -->
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>${rest-assured.version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>json-schema-validator</artifactId>
            <version>${rest-assured.version}</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <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>
                    <includes>
                        <include>**/*Test</include>
                    </includes>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.junit.jupiter</groupId>
                        <artifactId>junit-jupiter-engine</artifactId>
                        <version>${junit.jupiter.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                        <version>${junit.jupiter.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.version}</version>
                <configuration>
                    <parameters>true</parameters>
                    <!-- 设置jre版本为 11 -->
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <!-- 设置编码为 UTF-8 -->
                    <encoding>${maven.compiler.encoding}</encoding>
                </configuration>
            </plugin>

            <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>
        </plugins>
    </build>

解析封装

public class MapperUtil<T> implements  java.io.Serializable{
    private static final long serialVersionUID = 2L; // as of 2.9
    ObjectMapper objectMapper;

    T readValue ;


    public T getReadValue(String pathName){
        try {
            //兼容json yaml csv 解析
            if(pathName.endsWith(".json")){
                objectMapper = new ObjectMapper(new JsonFactory());
            }else if (pathName.endsWith(".yaml") | pathName.endsWith(".yml")){
                objectMapper = new ObjectMapper(new YAMLFactory());
            }else if(pathName.endsWith(".csv") ){
                objectMapper = new ObjectMapper(new CsvFactory());
            }
            TypeReference<T> valueTypeRef =
                    new TypeReference<T>() {};
            //解析数据
            readValue = objectMapper.readValue( new File(pathName), valueTypeRef);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return readValue;
    }

}

5.接口返回结果校验

  • body校验

  • code校验