java接口自动化测试框架及断言详解
作者:huowufenghuang 发布时间:2022-01-23 20:01:36
在上篇文章,我们介绍了Get方法的设计过程和测试结果,现在我们需要对前面代码进行重构和修改,本篇需要完成以下目标。
1)重构Get方法
2)如何进行JSON解析
3)使用TestNG方法进行测试断言
1.重构Get方法
在前面文章,说过,之前写的Get方法比较繁琐,不光写了如何进行Get请求,还写了获取http响应状态码和JSON转换。现在我们需要抽取出来,设计Get请求方法,就只干一件事情,那就是如何发送get请求,其他的不要管。
我们知道,请求之后会返回一个HTTP的响应对象,所以,我们把get方法的返回值类型改成了响应对象,并带上返回语句,重构代码之后,get方法代码如下。
package com.qa.restclient;
import java.io.IOException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
public class RestClient {
//1. Get 请求方法
public CloseableHttpResponse get(String url) throwsClientProtocolException, IOException {
//创建一个可关闭的HttpClient对象
CloseableHttpClienthttpclient = HttpClients.createDefault();
//创建一个HttpGet的请求对象
HttpGethttpget = newHttpGet(url);
//执行请求,相当于postman上点击发送按钮,然后赋值给HttpResponse对象接收
CloseableHttpResponsehttpResponse = httpclient.execute(httpget);
return httpResponse;
}
}
由于我们不想在代码里写死例如像HTTP响应状态码200这样的硬编码,所以,这里我们在TestBase.java里把状态码给用常量写出来,方便每一个TestNG测试用例去调用去断言。
package com.qa.base;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
public class TestBase {
public Properties prop;
public int RESPNSE_STATUS_CODE_200 = 200;
public int RESPNSE_STATUS_CODE_201 = 201;
public int RESPNSE_STATUS_CODE_404 = 404;
public int RESPNSE_STATUS_CODE_500 = 500;
//写一个构造函数
public TestBase() {
try{
prop= new Properties();
FileInputStreamfis = new FileInputStream(System.getProperty("user.dir")+
"/src/main/java/com/qa/config/config.properties");
prop.load(fis);
}catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
}
现在我们的测试类代码修改之后如下。
package com.qa.tests;
import java.io.IOException;
importorg.apache.http.client.ClientProtocolException;
importorg.apache.http.client.methods.CloseableHttpResponse;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.qa.base.TestBase;
import com.qa.restclient.RestClient;
public class GetApiTest extends TestBase{
TestBase testBase;
String host;
String url;
RestClient restClient;
CloseableHttpResponse closeableHttpResponse;
@BeforeClass
public void setUp() {
testBase = new TestBase();
host = prop.getProperty("HOST");
url = host + "/api/users";
}
@Test
public void getAPITest() throws ClientProtocolException, IOException {
restClient = new RestClient();
closeableHttpResponse= restClient.get(url);
//断言状态码是不是200
int statusCode = closeableHttpResponse.getStatusLine().getStatusCode();
Assert.assertEquals(statusCode,RESPNSE_STATUS_CODE_200, "response status code is not 200");
}
}
测试运行通过,没毛病。
2.写一个JSON解析的工具类
在上面部分,我们只是写了执行Get请求和状态码是否200的断言。接下来,我们需要写有一个JSON解析工具类,这样就方便我们去json内容的断言。
下面这个JSON数据截图
上面是一个标准的json的响应内容截图,第一个红圈”per_page”是一个json对象,我们可以根据”per_page”来找到对应值是3,而第二个红圈“data”是一个JSON数组,而不是对象,不能直接去拿到里面值,需要遍历数组。
下面,我们写一个JSON解析的工具方法类,如果是像第一个红圈的JSON对象,我们直接返回对应的值,如果是需要解析类似data数组里面的json对象的值,这里我们构造方法默认解析数组第一个元素的内容。
在src/main/java下新建一个包:com.qa.util,然后在新包下创建一个TestUtil.java类。
package com.qa.util;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
public class TestUtil {
/**
*
* @param responseJson ,这个变量是拿到响应字符串通过json转换成json对象
* @param jpath,这个jpath指的是用户想要查询json对象的值的路径写法
* jpath写法举例:1) per_page 2)data[1]/first_name ,data是一个json数组,[1]表示索引
* /first_name 表示data数组下某一个元素下的json对象的名称为first_name
* @return,返回first_name这个json对象名称对应的值
*/
//1 json解析方法
public static String getValueByJPath(JSONObject responseJson, String jpath){
Objectobj = responseJson;
for(String s : jpath.split("/")) {
if(!s.isEmpty()) {
if(!(s.contains("[") || s.contains("]"))) {
obj = ((JSONObject) obj).get(s);
}else if(s.contains("[") || s.contains("]")) {
obj =((JSONArray)((JSONObject)obj).get(s.split("\\[")[0])).get(Integer.parseInt(s.split("\\[")[1].replaceAll("]", "")));
}
}
}
return obj.toString();
}
}
简单解释下上面的代码,主要是查询两种json对象的的值,第一种最简单的,这个json对象在整个json串的第一层,例如上面截图中的per_page,这个per_page就是通过jpath这个参数传入,返回的结果就是3. 第二种jpath的查询,例如我想查询data下第一个用户信息里面的first_name的值,这个时候jpath的写法就是data[0]/first_name,查询结果应该是Eve。
3.TestNG测试用例
下面,我们TestNG测试用例代码如下
package com.qa.tests;
import java.io.IOException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.util.EntityUtils;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qa.base.TestBase;
import com.qa.restclient.RestClient;
import com.qa.util.TestUtil;
public class GetApiTest extends TestBase{
TestBase testBase;
String host;
String url;
RestClient restClient;
CloseableHttpResponse closeableHttpResponse;
@BeforeClass
public void setUp() {
testBase = new TestBase();
host = prop.getProperty("HOST");
url = host + "/api/users?page=2";
}
@Test
public void getAPITest() throws ClientProtocolException, IOException {
restClient = new RestClient();
closeableHttpResponse = restClient.get(url);
//断言状态码是不是200
int statusCode = closeableHttpResponse.getStatusLine().getStatusCode();
Assert.assertEquals(statusCode, RESPNSE_STATUS_CODE_200, "response status code is not 200");
//把响应内容存储在字符串对象
String responseString = EntityUtils.toString(closeableHttpResponse.getEntity(),"UTF-8");
//创建Json对象,把上面字符串序列化成Json对象
JSONObject responseJson = JSON.parseObject(responseString);
//System.out.println("respon json from API-->" + responseJson);
//json内容解析
String s = TestUtil.getValueByJPath(responseJson,"data[0]/first_name");
System.out.println(s);
}
}
运行测试结果:
[RemoteTestNG] detected TestNGversion 6.14.3
Eve
PASSED: getAPITest
你还可以多写几个jpath来测试这个json解析工具类。
String s = TestUtil.getValueByJPath(responseJson,"data[1]/id");
String s = TestUtil.getValueByJPath(responseJson,"per_page");4.TestNG自带的测试断言方法
这里简单提一下TestNG的断言方法,我们一般测试都需要写断言的代码,否则这样的单元测试代码就没有意义。下面,我在statusCode和json解析的first_name进行断言。
package com.qa.tests;
import java.io.IOException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.util.EntityUtils;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qa.base.TestBase;
import com.qa.restclient.RestClient;
import com.qa.util.TestUtil;
public class GetApiTest extends TestBase{
TestBase testBase;
String host;
String url;
RestClient restClient;
CloseableHttpResponse closeableHttpResponse;
@BeforeClass
public void setUp() {
testBase = new TestBase();
host = prop.getProperty("HOST");
url = host + "/api/users?page=2";
}
@Test
public void getAPITest() throws ClientProtocolException, IOException {
restClient = new RestClient();
closeableHttpResponse = restClient.get(url);
//断言状态码是不是200
int statusCode = closeableHttpResponse.getStatusLine().getStatusCode();
Assert.assertEquals(statusCode, RESPNSE_STATUS_CODE_200, "response status code is not 200");
//把响应内容存储在字符串对象
String responseString = EntityUtils.toString(closeableHttpResponse.getEntity(),"UTF-8");
//创建Json对象,把上面字符串序列化成Json对象
JSONObject responseJson = JSON.parseObject(responseString);
//System.out.println("respon json from API-->" + responseJson);
//json内容解析
String s = TestUtil.getValueByJPath(responseJson,"data[0]/first_name");
System.out.println(s);
Assert.assertEquals(s, "Eve","first name is not Eve");
}
}
经常使用的测试断言:
Assert.assertEquals(“现实结果”, "期待结果","断言失败时候打印日志消息");
来源:http://www.360doc.com/content/19/0107/11/16614840_807193642.shtml


猜你喜欢
- 我们知道,Maven 是通过仓库对依赖进行管理的,当 Maven 项目需要某个依赖时,只要其 POM 中声明了依赖的坐标信息,Maven 就
- FormClosing事件在窗体关闭时,FormClosing事件发生。此事件会得到处理。从而释放与窗体相关的所有资源。如果取消此事件,则窗
- mapper文件使用in("str1","str2")mybatis的xxxMapper.xml文件
- 静默安装就是偷偷的把一个应用安装到手机上,就是屏蔽确认框,通过反射只能写个主要的代码,这个是在linux编译用到,因为静默安装需要调用系统服
- 字符串的操作是C#程序设计中十分重要的一个组成部分,本文就以实例形式展现了C#实现移除字符串末尾指定字符的方法。相信对大家学习C#程序设计有
- 分享一个在项目中用的到文件上传下载和对图片的压缩,直接从项目中扒出来的:)package com.eabax.plugin.yundada.
- 1,内容简介所谓的定时调度,是指在无人值守的时候系统可以在某一时刻执行某些特定的功能采用的一种机制,对于传统的开发而言,定时调度的操作分为两
- 今天介绍下 Aspose.Words 对 word 中的图片进行删除string tempFile = Application.Startu
- 带搜索的ComboBox就是给ComboBox一个依赖属性的ItemSource,然后通过数据源中是否包含要查询的值,重新给ComboBox
- 最近几天一直在看Hadoop相关的书籍,目前稍微有点感觉,自己就仿照着WordCount程序自己编写了一个统计关联商品。需求描述:根据超市的
- 什么是banner组件?在许多Android应用上,比如爱奇艺客户端、百度美拍、应用宝等上面,都有一个可以手动滑动的小广告条,这就是bann
- 最近一门课要求编写一个上位机串口通信工具,我基于Java编写了一个带有图形界面的简单串口通信工具,下面详述一下过程,供大家参考 ^_^一:首
- 本文实例讲述了Android编程连接MongoDB及增删改查等基本操作。分享给大家供大家参考,具体如下:MongoDB简介Mongodb,分
- 本文总结分析了Android编程开发之EditText中inputType属性。分享给大家供大家参考,具体如下:android 1.5以后添
- 【程序1】 题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位、十位、个位的数字都
- 最近经常有人问Spring Cloud Feign如何上传文件。有团队的新成员,也有其他公司的兄弟。本文简单做个总结——早期的Spring
- 应用场景最近社区总有人发文章带上小广告,严重影响社区氛围,好气!对于这种类型的用户,就该永久拉黑!社区的安全框架使用了 spring-sec
- 下面展示一下FTP软件上传功能的过程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下1、上传前上传前选择好要将文件或文件夹上传到远程FTP
- 昨天有个刚学java的师弟发了个程序给我,说死活编译不过,老是报编码问题,自己试了一下,也出问题了...当我们编辑了一个Java源文件保存时
- 一、重载(Overload)重载是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。每个重载的方法(或者构造函数)都必须有