如何使用REST Assured执行API测试
现在API在软件趋势(例如移动应用程序、物联网等)中扮演着越来越重要的角色,对这些 API 进行适当的自动化测试变得不可或缺。有许多不同的工具可以帮助您在API 级别编写这些自动化测试。我将向您展示如何使用流行的开源工具之一来完成此任务:REST Assured。
REST Assured 是一个Java库,它提供了一种域特定语言(DSL),用于为 RESTful API编写功能强大、可维护的测试。在以下部分中,我将向您展示如何设置和配置 REST Assured、编写和运行 REST Assured 测试以及应用其一些强大的功能。我将使用真实世界的代码示例,您可以在自己的测试自动化工作中直接复制、运行和重用。
入门:配置
要开始使用REST Assured,只需将其作为依赖项添加到您的项目中即可。如果您使用的是Maven,请将以下条目添加到您的 pom.xml(更改版本号以反映您要使用的版本):
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>3.0.2</version>
<scope>test</scope>
</dependency>
对于Gradle:
testCompile 'io.rest-assured:rest-assured:3.0.2'
REST Assured 可以轻松地与现有的单元测试框架(例如 JUnit 和 TestNG)结合使用。对于本教程中提供的示例,我使用了 REST Assured 和 TestNG。
设置好 REST Assured 的导入后,将以下静态导入添加到您的测试类:
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
并且已准备好创建 REST Assured 测试。
测试:理解语法
在本教程中,我们将测试Ergast赛车数据库API,可在此处找到。此API提供与一级方程式比赛、车手、赛道等相关的历史数据。
为了说明使用 REST Assured 编写测试的方式,这里有一个测试,它以JSON格式检索 2017 年一级方程式赛季的赛道列表,并检查列表中是否有 20 个赛道:
@Test
public void test_NumberOfCircuitsFor2017Season_ShouldBe20() {
given().
when().
get("http://ergast.com/api/f1/2017/circuits.json").
then().
assertThat().
body("MRData.CircuitTable.Circuits.circuitId",hasSize(20));
}
请注意,REST Assured使用的 fluent API支持行为驱动开发(BDD) 中熟悉的 Given/When/Then 语法,从而使测试易于阅读并处理一切(设置、执行和验证)只需一行代码。
该hasSize() Hamcrest匹配计数的数量电路,这就是为什么你需要对Hamcrest添加为静态导入。Hamcrest 库包含一组匹配器,允许您创建各种验证,同时保持它们的可读性。
测试的验证部分执行以下操作:
捕获 API 调用的 (JSON) 响应
使用 Groovy GPath 表达式“MRData.CircuitTable.Circuits.circuitId”查询所有名为 circuitId 的元素
验证(使用前面提到的 Hamcrest 匹配器)生成的 circuitId 元素集合的大小为 20
有Hamcrest匹配器用于大量不同的检查,包括equalTo()平等,每种不超过()和GREATERTHAN()进行比较,hasItem()来检查集合是否包含给定的元素,等等。有关匹配器的完整列表,请参考Hamcrest 库文档。
要运行测试,只需使用与您选择的单元测试框架(即 JUnit 或 TestNG)相关联的测试运行器。
验证技术响应数据
使用 REST Assured,您不仅可以验证响应正文内容,还可以检查技术响应数据的正确性,例如 HTTP 响应状态代码、响应内容类型和其他响应标头。下面的示例检查:
响应状态代码等于 200。
响应内容类型(告诉响应的接收者如何解释响应正文)等于“application/json”。
响应头“Content-Length”的值等于“4567”。
@Test
这个例子还展示了如何使用and()方法以可读的方式轻松地连接检查,这只是语法糖,这意味着它所做的就是使代码更具可读性。
public void test_ResponseHeaderData_ShouldBeCorrect() {
given().
when().
get("http://ergast.com/api/f1/2017/circuits.json").
then().
assertThat().
statusCode(200).
and().
contentType(ContentType.JSON).
and().
header("Content-Length",equalTo("4567"));
}
参数化测试
通常,您需要使用不同的(输入和输出)参数集重复相同的测试——这个概念被称为数据驱动测试。您不需要为每个测试数据记录编写新测试,而是希望创建一个参数化测试,并根据所需的测试覆盖率向其提供尽可能多的测试数据记录。
RESTful API 支持两种不同类型的参数:
查询参数:这些参数附加在 RESTful API 端点的末尾,可以通过它们前面的问号来识别。例如,在端点 http://md5.jsontest.com/?text=test 中,“text”是一个查询参数(值为“test”)。
路径参数:这些是 RESTful API 端点的一部分。比如我们之前使用的端点:http://ergast.com/api/f1/2017/circuits.json,“2017”就是一个路径参数值。尝试将其替换为“2016”,看看会发生什么(提示:之前的测试应该失败,因为 2016 年有 21 场一级方程式比赛,而不是 20 场)。
REST Assured 可以使用这两种类型的参数。首先,让我们看看如何指定和使用上面示例中的查询参数:
@Test
public void test_Md5CheckSumForTest_ShouldBe098f6bcd4621d373cade4e832627b4f6() {
String originalText = "test";
String expectedMd5CheckSum = "098f6bcd4621d373cade4e832627b4f6";
given().
param("text",originalText).
when().
get("http://md5.jsontest.com").
then().
assertThat().
body("md5",equalTo(expectedMd5CheckSum));
}
如您所见,在 REST Assured 中使用查询参数就像使用param()方法指定它们的名称和值一样简单。路径参数以类似的方式指定:
@Test
public void test_NumberOfCircuits_ShouldBe20_Parameterized() {
String season = "2017";
int numberOfRaces = 20;
given().
pathParam("raceSeason",season).
when().
get("http://ergast.com/api/f1/{raceSeason}/circuits.json").
then().
assertThat().
body("MRData.CircuitTable.Circuits.circuitId",hasSize(numberOfRaces));
}
代替param(),路径参数是使用pathParam()方法定义的。此外,您需要定义端点路径的哪一部分代表路径变量,这是使用上面示例中看到的大括号表示法完成的。您可以以相同的方式轻松创建多个路径参数,如果 API 支持或需要,甚至可以在单个调用中组合路径和查询参数。
现在我们已经创建了一个参数化测试,通过使用外部测试数据集使其数据驱动是一项简单的任务。正如我在本教程开头所说的,使用 TestNG 容易做到这一点,但 JUnit 也支持参数化。使用 TestNG,您需要做的就是创建一个包含所需测试数据的DataProvider对象——在本例中,是一组包含年份和每年一级方程式比赛数量的记录:
@DataProvider(name="seasonsAndNumberOfRaces")
public Object[][] createTestDataRecords() {
return new Object[][] {
{"2017",20},
{"2016",21},
{"1966",9}
};
}
然后你只需通过测试方法参数将测试数据对象传递给参数化测试:
@Test(dataProvider="seasonsAndNumberOfRaces")
public void test_NumberOfCircuits_ShouldBe_DataDriven(String season, int numberOfRaces) {
given().
pathParam("raceSeason",season).
when().
get("http://ergast.com/api/f1/{raceSeason}/circuits.json").
then().
assertThat().
body("MRData.CircuitTable.Circuits.circuitId",hasSize(numberOfRaces));
}
当您有一个测试数据对象时,您可以通过创建、删除或修改适当的测试数据记录来添加、删除或更新单个测试用例。如果测试本身需要更新——例如当端点或响应主体结构发生变化时——您需要做的就是更新测试,所有测试用例都将遵循更新的过程。
访问安全 API
通常,API使用某种身份验证机制来保护。REST Assured支持基本、摘要、表单和 OAuth 身份验证。下面是如何调用使用基本身份验证保护的 RESTful API 的示例(即,此 API 的使用者每次调用 API 时都需要提供有效的用户名和密码组合):
@Test
public void test_APIWithBasicAuthentication_ShouldBeGivenAccess() {
given().
auth().
preemptive().
basic("username", "password").
when().
get("http://path.to/basic/secured/api").
then().
assertThat().
statusCode(200);
}
假设您拥有有效的身份验证令牌,访问受 OAuth2 保护的 API 也同样简单:
@Test
public void test_APIWithOAuth2Authentication_ShouldBeGivenAccess() {
given().
auth().
oauth2(YOUR_AUTHENTICATION_TOKEN_GOES_HERE).
when().
get("http://path.to/oath2/secured/api").
then().
assertThat().
statusCode(200);
}
在测试之间传递参数
通常,在测试 RESTful API 时,您可能需要创建更复杂的测试场景,您需要从一个 API 调用的响应中捕获一个值并在后续调用中重用它。REST Assured 使用extract()方法支持这一点。例如,这里有一个测试场景,它提取2017年一级方程式赛季一条赛道的ID,并使用它来检索和验证该赛道的附加信息(在本例中,赛道位于澳大利亚):
@Test
public void test_ScenarioRetrieveFirstCircuitFor2017SeasonAndGetCountry_ShouldBeAustralia() {
// First, retrieve the circuit ID for the first circuit of the 2017 season
String circuitId = given().
when().
get("http://ergast.com/api/f1/2017/circuits.json").
then().
extract().
path("MRData.CircuitTable.Circuits.circuitId[0]");
// Then, retrieve the information known for that circuit and verify it is located in Australia
given().
pathParam("circuitId",circuitId).
when().
get("http://ergast.com/api/f1/circuits/{circuitId}.json").
then().
assertThat().
body("MRData.CircuitTable.Circuits.Location[0].country",equalTo("Australia"));
}
使用 ResponseSpecBuilder 重用检查
提高 RESTful API 测试的可重用性和可维护性的另一种方法是重用特定检查。例如,如果您想检查所有 API 响应的状态代码是否等于 200,内容类型是否等于“application/json”,那么为每个测试指定此项会很快让人厌烦。
此外,如果由于某种原因默认状态代码和内容类型返回了更改,那么只需在一个地方而不是整个测试套件中更新它不是很好吗?REST Assured 支持使用 ResponseSpecBuilder 机制重用特定的验证。
下面是一个示例,说明如何创建可重用的 ResponseSpecification 来检查上述状态代码和内容类型,以及如何在测试中使用它:
ResponseSpecification checkStatusCodeAndContentType =
new ResponseSpecBuilder().
expectStatusCode(200).
expectContentType(ContentType.JSON).
build();
@Test
public void test_NumberOfCircuits_ShouldBe20_UsingResponseSpec() {
given().
when().
get("http://ergast.com/api/f1/2017/circuits.json").
then().
assertThat().
spec(checkStatusCodeAndContentType).
and().
body("MRData.CircuitTable.Circuits.circuitId",hasSize(20));
}
除了使用 ResponseSpecification 之外,您还可以创建特定于该测试的检查。
其他的REST Assured功能
除了上面介绍的那些之外,REST Assured 还提供了许多其他有用的功能,让您可以创建更强大的测试,例如:
能够(反)序列化普通旧 Java 对象 (POJO)。这允许您将与 Java 对象实例关联的属性和值直接序列化为 JSON 或 XML 文档,然后可以使用 POST 方法将其发送到 RESTful API。这也可以反过来工作——API 返回的 JSON 或 XML 响应也可以由 REST Assured 反序列化为 POJO 实例。
记录请求和响应。当您需要检查 API 响应以创建适当的检查时,或者当您想确保发送到 API 的请求正确时,这尤其有用。您可以选择记录所有内容(参数、标题和正文)、仅记录标题、仅记录参数等等。
REST Assured 带有一个 Spring Mock MVC 模块,允许您使用 REST Assured 语法为 Spring 控制器编写测试。
如何使用REST Assured执行API测试相关推荐
- 新手入门API测试必要了解的知识
什么是API?API是Application Programming Interface的简写.实现了两个或多个独立系统或模块间的通信和数据交换能力. 什么是API测试?API测试是不同于UI级自动化 ...
- 【收藏】什么是API测试?这是我见过的最全的测试指南!
在最近的部署中,当我被问到"什么是API测试?"时,我正与客户一起制定API测试策略.那时我突然意识到,要描述API测试居然是一件如此具有挑战性的事情,即使你如实地描述了它,也往往 ...
- API测试| 了解API接口测试| API接口测试指南
什么是API? API是一个缩写,它代表了一个 pplication P AGC软件覆盖整个房间.API是用于构建软件应用程序的一组例程,协议和工具.API指定一个软件程序应如何与其他软件程序进行交互 ...
- newman执行测试_用Postman/Newman搞定API测试
说到Postman相信大家都已经很熟悉了,我们平时用它可以做API测试,trouble shooting,辅助开发等,能够很方便的进行手工测试和调试. 今天我们来说postman除了这些功能之外的其他 ...
- katalon进行app测试_使用Katalon Studio创建你的第一个API测试
API测试(或WebService测试)在软件测试中变得越来越重要.根据谷歌趋势报告,过去五年来,行业内对API测试的兴趣一直在增加.这种趋势在一定程度上表明API测试的需求变得更加普遍.测试API或 ...
- soapui工具_基于开源的API测试工具!不再为web服务负载测试而发愁
通过一个可视化.拖拽式的界面,LoadUI允许您实时.交互式地创建.配置和重分配负载测试.在单一测试环境下,LoadUI提供完整的测试覆盖,支持所有标准的协议和技术.它功能强大,能从任意数量的本地和远 ...
- 一种基于openflow的虚拟化层软件flowvisor的API测试
注明:本文并不对openflow进行分析,本人也是略略知道这个概念,对flowvisor也只是对其API有所测试,更深的源码并未涉及,只是希望该文能对以后的flowvisor研究者提供些许帮助. 一: ...
- API测试和自动化101:基本指南
API代表A pplication P AGC软件我覆盖整个院落. 通常,API用于通过使用任何通信方式来促进两个不同应用程序之间的交互. 在网络上使用API时,我们将其称为" Web服 ...
- 接口测试php代码,简易 PHP API 测试
简易 PHP API 测试 PHP代码 /* ============================================================================= ...
- u8api openapi_使用OpenAPI规范进行更好的API测试
u8api openapi 如果在Internet上搜索"意外的API行为",您会很快发现,没有人喜欢API无法正常工作. 当您考虑API的数量不断增加,持续开发以及在其之上构建的 ...
最新文章
- 北大计算机博士生先于OpenAI发表预训练语言模型求解数学题论文,曾被顶会拒绝...
- http协议常见的响应头
- 系统要关闭,可我程序还有事要处理?
- 《代码大全2》读书笔记 Week2
- 017_CSS长度单位
- UVA 1451 Average 数形结合
- 结构体定义容易混淆的地方
- 妈妈帮携手神策数据 数据赋能打造母婴智能陪伴者
- MVC学习笔记2 认识项目的目录结构与核心的DLL
- REDIS一致性检查
- 小程序 遮罩层(阻止事件穿透)
- css 动画 - 这次不会忘记了
- 两篇讲述Skinned Mesh原理的文章
- err_cleartext_not_permitted
- 计算机连接双硬盘,电脑如何安装双硬盘
- python基础-解释器安装
- 日志文件的格式和内容,日志文件的作用,登记日志文件的规则
- 达梦数据库远程网页访问
- 代码读智识 笔墨知人心 1
- win10 安全设置
热门文章
- AH快递单打印软件(顺丰申通圆通韵达中通天天EMS) 3.77
- 网站出现502 BAD GATEWAY的解决办法
- [953]mongo创建索引及索引相关方法
- 用例图、功能模块图和数据库的区别
- 搭建一个独立英文网站费用多少?
- python中import re_彻底搞懂Python 中的 import 与 from import
- oracle不兼容win7 64位系统,解决oracle数据库在win7 64位操作系统下无法安装问题
- 应用出海之--AdMob
- 谷歌admob测试设备测试流程
- hdu 4899 Hero meet devil