Rest-Assure框架使用教程
- 一、概括:
- 一、简介:
- 二、优势
- 三、 环境准备
- 二、实战
- 一、新建一个测试类 TestRestAssured.java
- 二、接口请求构造
- 三、接口测试断言
- 四、json/xml请求
- 五、json/xml响应断言
- 六、Headers/Cookie 处理
- 七、form请求
- 八、超时处理
- 九、文件上传测试
- 十、代理配置
- 十、认证体系
- 十一、接口加密与解密
- 十二、多套环境测试
一、概括:
一、简介:
- 是由 Java 实现的 REST API 测试框架
- 支持发起 POST,GET,PUT,DELETE 等请求
- 可以用来验证和校对响应信息
- 官网地址: http://rest-assured.io
二、优势
- 简约的接口测试 DSL
- 支持 xml/json 的结构化解析
- 支持xpath/jsonpath/gpath解析方式
- 对 spring 的支持比较全面
- 符合契约编程思想
三、 环境准备
- 基于 JDK 11、JUnit5
- 创建 maven 项目
- pom.xml 添加 rest-assured 的依赖
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>4.4.0</version>
<scope>test</scope>
</dependency>
二、实战
一、新建一个测试类 TestRestAssured.java
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
public class TestRestAssured {
@Test
void fun(){
given()
// given 设置测试预设(请求头、请求参数、请求体等等)
.header("Hello", "Hogwarts")
.when()
// when 所要执行的请求动作
.get("https://httpbin.ceshiren.com/get")
.then()
// then 解析结果、断言
.log().all(); // 打印全部响应信息(响应头、响应体、状态等等)
}
附录:JUnit5 依赖配置
<!-- JUnit5 -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
二、接口请求构造
语法格式
given():可以设置测试预设
param():URL 查询参数 when():所要执行的操作
get():GET 请求
post():POST 请求
then():可以解析结果、断言
statusCode():响应状态码断言
- get请求
import static io.restassured.RestAssured.given;
import org.junit.jupiter.api.Test;
public class TestRestAssuredGet {
@Test
void testGet(){
given()
// 可以设置测试预设
.param("username", "Hogwarts") // 设置查询参数
.when()
// 发起 GET 请求
.get("https://httpbin.ceshiren.com/get")
.then()
// 解析结果
.log().all() // 打印完整响应信息
.statusCode(200); // 响应断言
}
- POST 请求
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
public class TestRestAssuredPost {
@Test
void testPost(){
given()
// 可以设置测试预设
.param("username", "Hogwarts") // 设置查询参数
.when()
// 发起 POST 请求
.post("https://httpbin.ceshiren.com/post")
.then()
// 解析结果
.log().all() // 打印完整响应信息
.statusCode(200); // 响应断言
}
- 请求参数
直接拼接在 URL 中
?username=Hogwarts&id=666
GET 请求
param():查询参数
POST 请求
queryParam():查询参数
formParam():表单参数
import static io.restassured.RestAssured.given;
import org.junit.jupiter.api.Test;
public class TestRestAssuredGet {
@Test
void testGet(){
given()
// 可以设置测试预设
.param("username", "Hogwarts") // 设置查询参数
.when()
// 发起 GET 请求
.get("https://httpbin.ceshiren.com/get")
.then()
// 解析结果
.log().all() // 打印完整响应信息
.statusCode(200); // 响应断言
三、接口测试断言
- 接口断言使用场景
问题: 如何确保请求可以发送成功 如何保证符合业务需求 解决方案: 响应断言
响应结果类型:
类型 | 断言方法 | 含义 |
状态码 | statusCode() | 响应状态码 |
响应头 | header() | 响应头信息 |
内容 | body() | 内容完全匹配 |
- 简单断言: 响应状态码
import static io.restassured.RestAssured.given;
import org.junit.jupiter.api.Test;
public class TestAssertionStatusCode {
@Test
void testStatusCode(){
given()
.when()
.get("https://httpbin.ceshiren.com/get") // 发起GET请求
.then()
.log().all() // 打印响应结果
.statusCode(200); // 响应状态码断言
- 简单断言: 响应体
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.core.IsEqual.equalTo;
public class TestAssertionBody {
@Test
void testBody(){
given()
.when()
.get("https://httpbin.ceshiren.com/get") // 发起GET请求
.then()
.log().all() // 打印响应结果
.body("origin", equalTo("113.89.246.184")); // 响应体断言
}
}
- 复杂断言
提问:若碰到复杂断言应该如何处理?
- jsonpath
- jsonschema
- 自行编写解析算法
- 附录:Hamcrest 依赖配置
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
四、json/xml请求
- json请求
1、简介
- 是 JavaScript Object Notation 的缩写
- 是一种轻量级的数据交换格式
- 是理想的接口数据交换语言
- 官网:https://www.json.org/json-en.html
2、json请求
1、构造 JSON 请求体
- JSON 字符串
- HashMap 对象 + Jackson库
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
public class TestJsonStr {
@Test
void testJsonRequest(){
// 定义请求体数据:json序列化后的字符串
String jsonStr = "{\"Hello2\": \"Hogwarts\"}";
given()
.contentType("application/json") // 设置请求内容类型
.body(jsonStr) // 设置请求体数据
.log().headers() // 打印请求头信息
.log().body() // 打印请求体信息
.when()
.post("https://httpbin.ceshiren.com/post") // 发送请求
.then()
.statusCode(200); // 响应状态码断言
- 使用 HashMap 对象
import java.util.HashMap;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
public class TestJsonObj {
@Test
void testJsonRequest(){
// 定义请求体数据:HashMap 对象
HashMap<String, String> jsonObj = new HashMap<>();
jsonObj.put("Hello", "Hogwarts");
given()
.contentType("application/json") // 设置请求内容类型
.body(jsonObj) // 定制请求体数据
.log().headers() // 打印请求头信息
.log().body() // 打印请求体信息
.when()
.post("https://httpbin.ceshiren.com/post") // 发送请求
.then()
.statusCode(200); // 响应状态码断言
}
}
2、XML
简介
- 是 eXtensible Markup Language 的缩写
- 是 可扩展标记语言,类似 HTML
- 是用来传输和存储数据
- 是通过 < > 标签来描述信息
- 是 W3C 的推荐标准
<?xml version="1.0"?>
<study>
<course>
<name>JUnit5测试框架</name>
<school>Hogwarts</school>
</course>
<course>
<name>接口自动化测试</name>
<school>Hogwarts</school>
</course>
</study>
xml请求
构建 XML 请求体
- 外部 XML 文件
- 字符串
- 示例接口地址:http://dneonline.com/calculator.asmx
- 外部 XML 文件
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<Add xmlns="http://tempuri.org/">
<intA>1</intA>
<intB>1</intB>
</Add>
</Body>
</Envelope>
- xml请求
import static io.restassured.RestAssured.*;
import org.junit.jupiter.api.Test;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class TestXML {
@Test
void testSoapApi() throws IOException {
// 定义请求体数据:源自文件对象
File file = new File("src/test/resources/add.xml");
FileInputStream fis = new FileInputStream(file);
String reqBody = IOUtils.toString(fis, "UTF-8");
given()
.contentType("text/xml") // 定制请求内容媒体类型
.body(reqBody) // 定制请求体数据
.log().headers() // 打印请求头信息
.log().body() // 打印请求体信息
.when()
.post("http://dneonline.com//calculator.asmx") // 发送请求
.then()
.statusCode(200); // 响应状态码断言
}
}
- 附录一:Jackson 依赖配置
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
<scope>test</scope>
</dependency>
- IOUtils 依赖配置
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
<scope>test</scope>
</dependency>
五、json/xml响应断言
1、XML 响应断言
- XPath简介
- 是 XML 路径语言
- 是 XML Path Language 的缩写
- 是用来确定 XML 文档中某部分位置
- XPath 语法
Xpath | 描述 |
/ | 根节点 |
. | 现行节点 |
// | 不管位置,选择所有符合条件的元素 |
* | 匹配所有元素节点 |
[ ] | 迭代器标示 |
| | 支持迭代器中做多选 |
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<Add xmlns="http://tempuri.org/">
<intA>1</intA>
<intB>2</intB>
</Add>
</Body>
</Envelope>
// 读取解析xml文件并做断言
@Test
void readXml() {
File file = new File("C:\\Users\\86189\\IdeaProjects\\java\\src\\main\\resources\\2.xml");
FileInputStream is = null;
try {
is = new FileInputStream(file);
String result = IOUtils.toString(is, "UTF-8");
given().contentType("text/xml").body(result)
.when()
.post("http://dneonline.com/calculator.asmx")
.then()
.body("//AddResult.text()",equalTo("3")).log().all();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
2、json响应断言
json简介
- 是 JavaScript Object Notation 的缩写
- 是一种轻量级的数据交换格式
- 是理想的接口数据交换语言
- 官网:https://www.json.org/json-en.html
json响应数据
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip,deflate",
"Hello": "Hogwarts",
"Host": "httpbin.ceshiren.com",
"User-Agent": "Apache-HttpClient/4.5.13 (Java/11.0.13)",
"X-Forwarded-Host": "httpbin.ceshiren.com",
"X-Scheme": "https"
},
"origin": "113.89.246.226",
"url": "https://httpbin.ceshiren.com/get"
}
jsonpath简介
- 是一种查询语言
- 是用来解析 JSON 数据
- 项目地址:https://github.com/json-path/JsonPath
jsonpath语法
JSONPath | 描述 |
$ | 根节点 |
@ | 现行节点 |
… | 不管位置,选择所有符合条件的元素 |
* | 匹配所有元素节点 |
. | 取子节点 |
[] | 取子节点,支持名称或者下标 |
[,] | 支持迭代器中做多选 |
?() | 支持过滤操作 |
语法示例
- 使用点号
$.address.city
$.phoneNumbers[0].number
$.phoneNumbers[*].number
$…number - 使用中括号
$[address][city]
$[phoneNumbers][0][number] - 过滤条件
$.phoneNumbers[?(@.type == ‘iPhone’)].number
JSONPath 响应断言
- REST assured 内置解析方法
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static io.restassured.path.json.JsonPath.from;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestJSONPathNested {
@Test
void fun() {
// 获取响应信息,并转成字符串对象
String resp = given()
.header("Hello", "Hogwarts")
.when()
.get("https://httpbin.ceshiren.com/get")
.then()
.log().body()
.extract().response().asString();
// 使用JSONPath解析响应体
String word = from(resp).getString("headers.Hello");
System.out.println(word);
// 响应断言
assertEquals("Hogwarts", word);
- 第三方 json-path解析方法
package ch06;
import com.jayway.jsonpath.JsonPath;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestJSONPathStandalone {
@Test
void fun() {
// 获取响应信息,并转成字符串对象
String resp = given()
.header("Hello", "Hogwarts")
.when()
.get("https://httpbin.ceshiren.com/get")
.then()
.extract().response().asString();
// 使用JSONPath解析响应体
String word = JsonPath.read(resp, "$.headers.Hello");
System.out.println(word);
// 响应断言
assertEquals("Hogwarts", word);
}
}
- 附录:JSONPath 依赖配置
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.6.0</version>
<scope>test</scope>
</dependency>
六、Headers/Cookie 处理
1、Headers 简介
- HTTP Headers 也叫做 HTTP 消息头
- 允许客户端和服务器传递附加信息
- 由名称、冒号、具体的值组成
- 设置请求 Headers
package ch09;
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
public class TestHeader {
@Test
void testSetHeader() {
// 配置本地代理,方便监听请求信息
RestAssured.proxy = host("localhost").withPort(8888);
given()
.header("User-Agent", "hogwarts") // 设置请求头
.relaxedHTTPSValidation() // 忽略HTTPS校验
.when()
.get("https://httpbin.ceshiren.com/get") // 发送请求
.then()
.log().all() // 打印完整响应信息
.statusCode(200); // 响应断言
}
}
2、Cookie 简介
添加 Cookie 的两种方式
- 通过 header() 方法
- 通过 cookie() 方法
- 设置请求 Cookie
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
public class TestCookieByHeader {
@Test
void testAddCookieByHeader() {
// 配置本地代理,方便监听请求信息
RestAssured.proxy = host("localhost").withPort(8888);
// 通过header()方法设置Cookie
given()
.header("Cookie", "my_cookie1=hogwarts") // 设置Cookie
.relaxedHTTPSValidation() // 忽略HTTPS校验
.when()
.get("https://httpbin.ceshiren.com/get") // 发送请求
.then()
.log().all() // 打印完整响应信息
.statusCode(200); // 响应断言
}
}
- 设置请求 Cookie
package ch09;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
public class TestCookie {
@Test
void testAddCookie() {
// 配置本地代理,方便监听请求信息
RestAssured.proxy = host("localhost").withPort(8888);
// 添加单个Cookie
given()
.cookie("my_cookie", "hogwarts") // 设置Cookie
.relaxedHTTPSValidation() // 忽略HTTPS校验
.when()
.get("https://httpbin.ceshiren.com/get") // 发送请求
.then()
.log().all() // 打印完整响应信息
.statusCode(200); // 响应断言
}
}
七、form请求
1、form 表单请求简介
- application/x-www-form-urlencoded
应用场景 - 数据量不大
- 数据层级不深的情况
- 通常以键值对传递
- form 表单请求的使用
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static io.restassured.specification.ProxySpecification.host;
public class TestFormParam {
@Test
void testFormParam() {
// 配置本地代理,方便监听请求信息
RestAssured.proxy = host("localhost").withPort(8888);
// 忽略HTTPS校验
RestAssured.useRelaxedHTTPSValidation();
// 发送 POST 请求
given()
.formParam("username", "hogwarts") // 添加表单数据
.log().headers() // 打印请求头信息
.log().body() // 打印请求体信息
.when()
.post("https://httpbin.ceshiren.com/post") // 发送请求
.then()
.statusCode(200); // 响应断言
}
}
// 调用 formParams() 方法
public class TestFormParams {
@Test
void testFormParams() {
// 配置本地代理,方便监听请求信息
RestAssured.proxy = host("localhost").withPort(8888);
// 忽略HTTPS校验
RestAssured.useRelaxedHTTPSValidation();
// 发送 POST 请求
given()
.formParams("username", "hogwarts",
"pwd", "666") // 添加表单数据
.log().headers()
.log().body()
.when()
.post("https://httpbin.ceshiren.com/post") // 发送请求
.then()
.statusCode(200); // 响应断言
}
}
八、超时处理
- 1、为什么需要请求超时处理
- 设置请求超时的效果
- 设置超时时间:超时后会停下来,然后报错
import io.restassured.RestAssured;
import io.restassured.config.HttpClientConfig;
import io.restassured.config.RestAssuredConfig;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
public class TestTimeout {
@BeforeAll
static void setupClass(){
RestAssured.baseURI = "https://httpbin.ceshiren.com";
}
@Test
void case1() {
given()
.when()
.get("/get") // 发送GET请求
.then()
.statusCode(200); // 响应断言
}
@Test
void case2(){
// 自定义HttpClientConfig对象
// 设置响应超时时长为3秒,单位是毫秒
HttpClientConfig clientConfig = HttpClientConfig
.httpClientConfig()
.setParam("http.socket.timeout", 3000);
// 定义RestAssuredConfig对象
// 传入自定义的HttpClientConfig对象
RestAssuredConfig myTimeout = RestAssuredConfig
.config()
.httpClient(clientConfig);
// 接口调用
given()
.config(myTimeout) // 设置超时处理
.when()
.get("/delay/10") // 特定接口,延迟10秒响应
.then()
.statusCode(200); // 响应断言
}
@Test
void case3(){
given()
.when()
.get("/get") // 发送GET请求
.then()
.statusCode(200); // 响应断言
}
}
九、文件上传测试
1、文件上传接口场景
- Content-Type 类型:multipart/form-data
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import java.io.File;
import static io.restassured.RestAssured.given;
import static io.restassured.specification.ProxySpecification.host;
public class TestMultiPart {
/**
1,创建本地文件
hogwarts.txt
2,调用方法
multiPart()
参数:String name
参数:File file
*/
@Test
void testUploadFile(){
// 需要上传的文件对象
File myFile = new File("src/test/resources/hogwarts.txt");
// 定义一个代理的配置信息
RestAssured.proxy = host("localhost").withPort(8888);
// 忽略HTTPS校验
RestAssured.useRelaxedHTTPSValidation();
given()
.multiPart("hogwarts", myFile) // 传递文件对象
.log().headers() // 打印请求消息头
.log().body() // 打印请求消息体
.when()
.post("https://httpbin.ceshiren.com/post") //发送POST请求
.then()
.statusCode(200); // 响应断言
}
}
- 携带多种数据
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import java.io.File;
import static io.restassured.RestAssured.given;
import static io.restassured.specification.ProxySpecification.host;
public class TestMultiParts {
@Test
void testUploadFiles(){
// 需要上传的文件对象
File myFile = new File("src/test/resources/hogwarts.txt");
// 定义一个代理的配置信息
RestAssured.proxy = host("localhost").withPort(8888);
// 忽略HTTPS校验
RestAssured.useRelaxedHTTPSValidation();
given()
.multiPart("hogwarts", myFile) // 传递文件对象
.multiPart("ceshiren", "{\"hogwarts\": 666}",
"application/json") // 传递JSON数据
.log().headers() // 打印请求消息头
.log().body() // 打印请求消息体
.when()
.post("https://httpbin.ceshiren.com/post") // 发送POST请求
.then()
.statusCode(200); // 响应断言
}
}
十、代理配置
1、代理简介
- 介于客户端与服务器之间
- 可以监听请求和响应信息
- 充当防火墙和 Web 过滤器
2、代理前后对比
3、代理与接口测试
- 更直观的排查请求错误
- 获取正确的的接口请求与响应信息
- 开启代理工具监听请求
- 获取自动化测试的请求与响应信息
- 对比两次请求响应的区别
4、REST assured 使用代理 - 开启代理工具监听请求
- 配置代理
局部:通过 proxy() 方法
全局:定义 proxy 对象
5、使用代理请求 HTTP
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static io.restassured.specification.ProxySpecification.host;
public class TestHttpProxyConf {
@Test
void testHTTPProxy() {
// 定义一个代理的配置信息(也可以直接添加proxy参数)
given()
.proxy("localhost",8888) // 设置代理
// .proxy("127.0.0.1",8889) // 代理的3种写法
.when()
.get("http://httpbin.org/get") // 发送 HTTP请求
.then()
.log().all() // 打印完整响应信息
.statusCode(200); // 响应断言
}
}
- 使用代理请求 HTTPS
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static io.restassured.specification.ProxySpecification.host;
public class TestHttpsProxyConf {
@Test
void testHTTPProxy() {
// 定义一个代理的配置信息
RestAssured.proxy = host("localhost").withPort(8888);
given()
.relaxedHTTPSValidation() // 忽略HTTPS校验
.when()
.get("https://httpbin.ceshiren.com/get")
.then()
.log().all() // 打印完整响应信息
.statusCode(200); // 响应断言
}
}
十、认证体系
1、认证体系简介
- 是验证通信发送者的数字身份的过程
- REST-assured 认证方案
OAuth
digest
certificate 证书认证
form 表单认证
basic authentication 基本认证
- 使用基本认证
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static io.restassured.specification.ProxySpecification.host;
/**
操作步骤:
- 开启本地代理
- 编写接口测试用例
- 执行测试用例
*/
public class TestAuth {
@Test
void testAuth(){
// 定义一个代理的配置信息
RestAssured.proxy = host("localhost").withPort(8888);
// 忽略HTTPS校验
RestAssured.useRelaxedHTTPSValidation();
// 被测接口地址
String testURL = "https://httpbin.ceshiren.com/basic-auth/hogwarts/666";
given()
.auth().basic("hogwarts", "666") // 设置基本认证
.when()
.get(testURL) // 发送GET请求
.then()
.statusCode(200); // 响应断言
}
}
十一、接口加密与解密
1、加密解密简介
- 加密:明文转换成密文的过程
- 解密:密文还原成明文的过程
- 常见加密算法
AES
RSA
MD5
Base64
2、解密方案
- 通用加密算法:使用对应解密算法
- 自研加密算法:研发提供加解密 lib
- 第三方加密服务:寻求加密方提供远程解析服务
3、接口解密实战
import org.apache.commons.codec.binary.Base64;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
public class TestBase64 {
@Test
void testEncodeAndDecode(){
// 加密一串数据:hogwarts
// 获取字节数组
byte[] arr1 = "hogwarts".getBytes(StandardCharsets.UTF_8);
// 执行加密
String encodedMsg = Base64.encodeBase64String(arr1);
// 解密一串数据:aG9nd2FydHM=
// 执行解密
byte[] arr2 = Base64.decodeBase64("aG9nd2FydHM=");
// 生成字符串
String decodeMsg = new String(arr2, StandardCharsets.UTF_8);
}
}
- 解密后响应断言
import org.apache.commons.codec.binary.Base64;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import static io.restassured.RestAssured.given;
public class TestDecode {
@Test
void testDecode(){
// 加密一串数据
byte[] data = "hogwarts".getBytes(StandardCharsets.UTF_8);
String secretMsg = Base64.encodeBase64String(data);
// 发起请求,并获取响应信息
LinkedHashMap<String, String> responseForm =
given()
.formParam("msg", secretMsg) // 提交表单数据
.when()
.post("https://httpbin.ceshiren.com/post") // 发起POST请求
.then()
.log().all() // 打印完整响应信息
.extract().path("form"); // 提取form信息
// 提取加密字段
String encodedMsg = responseForm.get("msg");
// 解密操作
String decodedMsg = new String(Base64.decodeBase64(encodedMsg));
// 响应断言
Assertions.assertEquals("hogwarts", decodedMsg);
}
}
十二、多套环境测试
1、多套环境测试背景
- 集成测试环境
- 验收测试环境
- 灰度测试环境
2、多套环境测试解决方案
- 测试环境 1
域名:http://httpbin.org
接口:/get - 测试环境 2
域名:https://httpbin.ceshiren.com
接口:/get
3、解决方案:
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
/**
多套环境测试方案(一)
痛点
- 硬编码耦合
- 维护成本高
*/
public class TestEnv {
@Test
void testOrg(){
// 测试org环境接口
given()
.when()
.get("http://httpbin.org/get") // 发送GET请求
.then()
.statusCode(200);
}
@Test
void testCeshiren(){
// 测试ceshiren环境接口
given()
.when()
.get("https://httpbin.ceshiren.com/get") // 发送GET请求
.then()
.statusCode(200);
}
}
/**
多套环境测试方案(二)
优点
通过配置信息管理环境
痛点
多个测试文件维护成本高
*/
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import static io.restassured.RestAssured.given;
public class TestEnvConf {
@BeforeAll
static void setupClass(){
// 实例化环境配置对象
HashMap<String, String> envs = new HashMap<>();
// 测试环境1的域名配置
envs.put("org", "http://httpbin.org/get");
// 测试环境1的域名配置
envs.put("ceshiren", "http://httpbin.ceshiren.com/get");
// 选定默认环境名称,方便灵活切换
envs.put("default", "org");
// 设置基路径,值为选定的域名地址
RestAssured.baseURI = envs.get(envs.get("default"));
}
@Test
void testEnvs(){
given()
.when()
.get("/get") // 发送GET请求
.then();
}
}
/**
多套环境测试方案(三)
最佳实践:配置文件
*/
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import static io.restassured.RestAssured.given;
public class TestEnvYaml {
@BeforeAll
static void setupClass() throws IOException {
/*
使用Jackson读取yaml文件
*/
// 实例化一个ObjectMapper 对象
ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
// 读取 resources 目录中的envs.yaml文件
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
File yamlFile = new File(classLoader.getResource("envs.yaml").getFile());
// 定义序列化的结构 TypeReference
TypeReference<HashMap<String, String>> typeRef = new
TypeReference<HashMap<String, String>>() {};
// 解析envs.yaml文件内容
HashMap<String, String> envs = objectMapper.readValue(yamlFile, typeRef);
// 设置基路径,值为选定的域名地址
RestAssured.baseURI = envs.get(envs.get("default"));
}
@Test
void testEnvs() {
//发起请求
given()
.when()
.get("/get")
.then()
.statusCode(200);
}
}