REST Assured API 自动化测试教程(示例)

什么是 Rest Assured?

Rest Assured 允许您使用 Java 库测试 REST API,并与 Maven 良好集成。它具有非常高效的匹配技术,因此断言您的预期结果也相当直接。Rest Assured 具有从请求和响应的几乎所有部分获取数据的方法,无论 JSON 结构有多复杂。

对于测试社区而言,API 自动化测试仍然是新的和小众的领域。JSON 的复杂性使得 API 测试尚未被充分探索。但这并不意味着它在测试过程中不重要。Rest Assured.io 框架通过使用核心 Java 基础知识使其变得非常简单,使其成为一个非常值得学习的东西。

为什么需要 Rest-Assured?

想象一下,您打开谷歌地图,寻找您想去的地方,您立即看到附近的餐馆,看到通勤选项;来自一些领先的旅游提供商,并且指尖有如此多的选项。我们都知道它们不是谷歌的产品,那么谷歌是如何做到展示它们的呢?他们使用这些提供商公开的 API。现在,如果要求您测试这种设置,即使在 UI 建成或开发中之前,测试 API 变得极其重要,并且重复测试它们,使用不同的数据组合使其非常适合自动化。

早些时候,我们使用 Groovy、Ruby 等动态语言来实现这一点,这很有挑战性。因此,功能测试没有探索 API 测试。

但是使用 Rest Assured,API 的自动化测试,发送带有用户友好自定义的简单 HTTPS 请求,如果一个人有 Java 基础,则很简单。需要了解 API 测试和集成测试,但在此之后,Rest Assured 自动化在后端提供了很好的信心,而前端测试可以只关注 UI 和客户端操作。Rest Assured 是一个开源工具,添加了许多额外的方法和库,使其成为 API 自动化的绝佳选择。

如何使用 Eclipse 设置 Rest Assured.io

步骤 1) 安装 Java。请参阅此指南

步骤 2) 下载 IDE 以开始:Eclipse

步骤 3) 安装 Maven 并设置您的 Eclipse。请参阅此处

设置 Rest Assured

  1. 在您的 IDE 中创建一个 Maven 项目。我们使用的是 Intellij,但您在任何您可能正在使用的 IDE 上都会获得类似的结构。
  2. 打开您的 POM.xml
Project structure
项目结构

对于 Rest Assured.io:对于 Java 版本 < 9 的用户

将以下依赖项添加到您的 POM.xml

<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>json-path</artifactId>
<version>4.2.0</version>
<scope>test</scope>
</dependency>


<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>xml-path</artifactId>
<version>4.2.0</version>
<scope>test</scope>
</dependency>


<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>json-schema-validator</artifactId>
<version>4.2.0</version>
<scope>test</scope>
</dependency>

对于 Rest Assured.io:对于 Java 版本 9+ 的用户

<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured-all</artifactId>
<version>4.2.0</version>
<scope>test</scope>
</dependency>

故障排除

如果您看到错误并且不确定依赖项是否已正确下载,

  1. 执行 Maven 构建以导入所有依赖项,您可以在 guru99 上找到有关 Maven 设置的帮助。
  2. 如果您仍然看到错误,请执行 Maven clean,然后执行 Maven install,它应该会无错误地构建。
  3. 您可以将以下行添加到您的 Java 类中,并且不会出现编译错误。
import io.restassured.RestAssured.*;
import io.restassured.matcher.RestAssuredMatchers.*;
import org.hamcrest.Matchers.*;

第一个简单的 Rest Assured 脚本

语法

Rest Assured.io 的语法是最美妙的部分,因为它非常像 BDD 并且易于理解。

Given(). 
        param("x", "y"). 
        header("z", "w").
when().
Method().
Then(). 
        statusCode(XXX).
        body("x, ”y", equalTo("z"));

解释

代码 解释
Given() “Given”关键字允许您设置背景,在这里,您传递请求头、查询和路径参数、正文、Cookie。如果请求中不需要这些项,则此项是可选的
When() “when”关键字标记了您场景的前提。例如,“when”您获取/发布/放置某物时,执行其他操作。
Method() 用任何 CRUD 操作(get/post/put/delete)替换此项
Then() 您的断言和匹配器条件在此处

现在您已经设置好并且对语法有了一些背景知识,让我们创建第一个简单的测试。如果到目前为止结构对您来说看起来很新,没关系,当您进一步编写代码并解释每一行时,您就会掌握它。

您将获取什么?

打开浏览器并访问 – https://demo.guru99.com/V4/sinkministatement.php?CUSTOMER_ID=68195&PASSWORD=1234!&Account_No=1。确保您看到如下内容。

Rest Assured script

如果您在尝试获取请求响应时在浏览器上遇到错误,

  1. 检查您是否使用了 Https 或 Http。您的浏览器可能设置了不打开不安全的网站。
  2. 检查是否有任何代理或防火墙阻止您的浏览器打开网站。

*注意 – 您在此处没有使用任何头部,没有正文,也没有 Cookie。这是一个 URL,而且您正在从 API 获取内容,而不是发布或更新任何现有内容,因此这是一个 GET 调用。请记住这一点,以便更好地理解我们的第一个测试。

您的测试目标

脚本的目标是,通过 Rest Assured,在您的 IDE 控制台上打印与您在浏览器上收到的相同的输出。

让我们使用以下步骤编写代码

获取响应正文

步骤 1) 创建一个名为“myFirstRestAssuredClass”的类

步骤 2) 创建一个名为“getResponseBody”的方法

步骤 3) 类似于之前学过的给定、when 和 then 结构,键入以下代码

given(). -> 不需要任何头部,不需要查询或路径参数。

when(). -> 没有特定的条件设置

get(‘https://demo.guru99.com/V4/sinkministatement.php?CUSTOMER_ID=68195&PASSWORD=1234!&Account_No=1‘). ->只需提供 URL

then(). -> 不需要特定的断言

log(). all() -> 获取所有响应后,记录响应、头部,本质上是请求返回给您的所有内容。

public static void getResponseBody(){
   given().when().get("https://demo.guru99.com/V4/sinkministatement.php?CUSTOMER_ID=68195&PASSWORD=1234!&Account_No=1").then().log()
  .all();
 
}

现在请注意,使用的 URL 很长且可读性较差,如果您仔细观察,您会发现正在使用 3 个查询参数,它们是

  1. 客户 ID
  2. 密码
  3. 帐号

Rest Assured 帮助我们分别传递每个部分(查询、路径、头部参数),使代码更具可读性且易于维护。此外,我们可以根据需要从外部文件参数化数据。

为了使用查询参数,我们回到语法的定义,看到所有参数都作为给定的一部分传递。

public static void getResponseBody(){
 
   given().queryParam("CUSTOMER_ID","68195")
           .queryParam("PASSWORD","1234!")
           .queryParam("Account_No","1")
           .when().get("https://demo.guru99.com/V4/sinkministatement.php").then().log()
           .body();
}

**请注意,我们使用了“body”而不是“all”;这有助于我们只提取响应的正文。

输出

获取响应状态码

我们编写的下一个方法是获取状态码,并进行断言以验证其正确性。

步骤 1) 创建一个名为 getResponseStatus() 的方法

步骤 2) 使用上面相同的请求结构。复制并粘贴。

步骤 3) 我们不记录它,而是使用 Rest Assured 的内置方法 'getStatusCode' 来获取状态码值

步骤 4) 为了断言您的状态码是 200,我们使用关键字 – assertThat().statusCode(expectedCode)

**注意 – URL 是一个为简化起见而使用的变量。URL 包含整个 API 请求 URL

public static void getResponseStatus(){
   int statusCode= given().queryParam("CUSTOMER_ID","68195")
           .queryParam("PASSWORD","1234!")
           .queryParam("Account_No","1") .when().get("https://demo.guru99.com/V4/sinkministatement.php").getStatusCode();
   System.out.println("The response status is "+statusCode);

   given().when().get(url).then().assertThat().statusCode(200);
}

输出

业务需求

自动化的基本规则之一是,我们必须设置检查点,以便只有在满足所有必需条件时,测试才能继续进行。在 API 测试中,最基本的验证是检查请求的状态码是否为 2XX 格式。

到目前为止的完整代码

import java.util.ArrayList;
import static io.restassured.RestAssured.*;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

public class myFirstRestAssuredClass {

   final static String url="https://demo.guru99.com/V4/sinkministatement.php?CUSTOMER_ID=68195&PASSWORD=1234!&Account_No=1";

   public static void main(String args[]) {

     getResponseBody();
     getResponseStatus();

; }

   //This will fetch the response body as is and log it. given and when are optional here
   public static void getResponseBody(){
       given().when().get(url).then().log()
      .all();

  given().queryParam("CUSTOMER_ID","68195")
               .queryParam("PASSWORD","1234!")
               .queryParam("Account_No","1") .when().get("https://demo.guru99.com/V4/sinkministatement.php").then().log().body();
   }

public static void getResponseStatus(){
   int statusCode= given().queryParam("CUSTOMER_ID","68195")
           .queryParam("PASSWORD","1234!")
           .queryParam("Account_No","1")
           .when().get("https://demo.guru99.com/V4/sinkministatement.php").getStatusCode();
   System.out.println("The response status is "+statusCode);

   given().when().get(url).then().assertThat().statusCode(200);
}

}

*注意

  1. 200 是此场景的成功响应。有时,您也需要请求失败,然后您可能会使用 4XX 或 5XX。请尝试通过提供无效参数来更改状态码并进行检查。
  2. 当我们断言一个条件时,除非出现错误,否则控制台上不会有任何打印。

获取响应不同部分的脚本

获取响应正文和响应状态码已在上述部分中介绍。值得注意的是,要获取响应的不同部分,“extract”关键字非常重要。

Header

Rest Assured 是一种非常直接的语言,获取头部同样简单。方法名称是 headers()。和以前一样,我们将创建一个独立的 方法来完成相同的操作。

public static void getResponseHeaders(){
   System.out.println("The headers in the response "+
                   get(url).then().extract()
           .headers());
}

请注意,这里省略了“given().when()”,代码行从 get() 开始,这是因为这里没有进行任何前置条件或验证来发起请求并获得响应。在这种情况下,使用它是可选的。

输出

业务需求

很多时候,您需要为后续请求使用授权令牌或会话 Cookie,而且这些详细信息通常作为响应的头部返回。

响应时间

为了获取从后端或其他下游系统获取响应所需的时间,Rest Assured 提供了一个名为“timeIn”的方法,该方法带有合适的 timeUnit,以获取返回响应所需的时间。

public static void getResponseTime(){
  System.out.println("The time taken to fetch the response "+get(url)
         .timeIn(TimeUnit.MILLISECONDS) + " milliseconds");
}

输出

业务需求

测试 API 的一个非常重要的特性是它们的响应时间,以衡量应用程序的性能。请注意,您的调用所需的时间可能会因您的互联网速度、当时 API 的性能、服务器负载以及影响时间的其它因素而异。

内容类型

您可以使用方法“contentType ()”获取返回响应的内容类型。

public static void getResponseContentType(){
   System.out.println("The content type of response "+
           get(url).then().extract()
              .contentType());
}

输出

业务需求

有时,获取内容类型对于确保没有跨域威胁的安全漏洞或仅仅是为了确保传递的内容符合 API 标准至关重要。

获取单个 JSON 元素

从给定的响应中,要求您计算总金额,您需要获取每个金额并求和。

步骤

步骤 1) 金额字段位于一个键为“statements”的数组中,该数组又位于键为“result”的列表中

步骤 2) Rest Assured 提供了一种使用“path”访问 API 中值 的机制

步骤 3) 到达金额的路径是“result.statements.AMOUNT”。把它想象成 Selenium 中的 Xpath。

步骤 4) 将所有金额收集到一个集合中,然后循环所有值以计算总和

public static void getSpecificPartOfResponseBody(){

ArrayList<String> amounts = when().get(url).then().extract().path("result.statements.AMOUNT") ;
int sumOfAll=0;
for(String a:amounts){

    System.out.println("The amount value fetched is "+a);
    sumOfAll=sumOfAll+Integer.valueOf(a);
}
System.out.println("The total amount is "+sumOfAll);

}

注意:由于金额值是字符串数据类型,我们将其转换为整数并用于求和。

输出

摘要

  • Rest Assured 是一组 Java 库,它使我们能够自动化 Rest API 测试
  • Rest Assured 基于 Java,掌握核心 Java 知识足以学习它
  • 它有助于从复杂的 JSON 结构中获取请求和响应的值
  • 可以自定义 API 请求,包括各种头部、查询、路径参数以及任何要设置的会话或 Cookie。
  • 它有助于设置断言语句和条件。
  • 虽然 Rest Assured 在响应为 JSON 类型时非常有用,但如果内容类型是 HTML 或纯文本,其方法可能无法无缝工作。