java接口自动化测试框架及断言详解

在上篇文章,我们介绍了Get方法的设计过程和测试结果,现在我们需要对前面代码进行重构和修改,本篇需要完成以下目标。

  • 1)重构Get方法
  • 2)如何进行JSON解析
  • 3)使用TestNG方法进行测试断言

1.重构Get方法

在前面文章,说过,之前写的Get方法比较繁琐,不光写了如何进行Get请求,还写了获取http响应状态码和JSON转换。现在我们需要抽取出来,设计Get请求方法,就只干一件事情,那就是如何发送get请求,其他的不要管。

我们知道,请求之后会返回一个HTTP的响应对象,所以,我们把get方法的返回值类型改成了响应对象,并带上返回语句,重构代码之后,get方法代码如下。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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测试用例去调用去断言。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

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();

     }

   }

}

现在我们的测试类代码修改之后如下。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

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类。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

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测试用例代码如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

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);

    }  

}

运行测试结果:

1

2

3

4

5

[RemoteTestNG] detected TestNGversion 6.14.3

Eve

PASSED: getAPITest

你还可以多写几个jpath来测试这个json解析工具类。

1

2

String s = TestUtil.getValueByJPath(responseJson,"data[1]/id");

String s = TestUtil.getValueByJPath(responseJson,"per_page");

4.TestNG自带的测试断言方法

这里简单提一下TestNG的断言方法,我们一般测试都需要写断言的代码,否则这样的单元测试代码就没有意义。下面,我在statusCode和json解析的first_name进行断言。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

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");

    }

}

经常使用的测试断言:

1

Assert.assertEquals(“现实结果”, "期待结果","断言失败时候打印日志消息");

​现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:485187702【暗号:csdn11】

最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走! 希望能帮助到你!【100%无套路免费领取】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/225518.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

家政小程序源码,师傅竞价接单

家政预约上门服务小程序开发方案,php开发语言,前端是uniapp,有成品源码,可以二开,可以定制。 一家政小程序用户端功能:服务分类、在线预约、在线下单。 师傅端:在线接单,竞价&…

算法初阶双指针+C语言期末考试之编程题加强训练

双指针 常⻅的双指针有两种形式,⼀种是对撞指针,⼀种是左右指针。 对撞指针:⼀般⽤于顺序结构中,也称左右指针。 • 对撞指针从两端向中间移动。⼀个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼…

哥尼斯堡的“七桥问题”——欧拉回路

哥尼斯堡是位于普累格河上的一座城市,它包含两个岛屿及连接它们的七座桥,如下图所示。 可否走过这样的七座桥,而且每桥只走过一次?瑞士数学家欧拉(Leonhard Euler,1707—1783)最终解决了这个问题,并由此创立…

Pacifist:一款专为技术开发者打造的软件提取工具

对于技术开发者而言,有效且便捷的工具可以显著提高工作效率。Pacifist,作为一款专业的软件提取工具,专为技术开发者而设计,旨在提供简单、安全的软件提取和管理工作。 一、Pacifist的技术特点 Pacifist主要采用AppleScript作为其…

ROS小练习——话题订阅

目录 一、话题与消息获取 二、代码编写 1、C 2、python 三、编译运行 一、话题与消息获取 rostopic list rostopic type /turtle1/pose rosmsg info turtlesim/Pose 二、代码编写 1、C //包含头文件 #include "ros/ros.h" #include "turtlesim/Pose…

js vue 输入正确手机号/邮箱后,激活“发送验证码”按钮

按钮禁止点击状态: 按钮能够点击状态: 我采用的方式是监听手机号/邮箱输入框的输入事件,即实判断用户输入的数据是否满足规则,如果满足手机号/邮箱规则,则激活“获取验证码”按钮。 话不多说,上代码 样式…

Java期末复习题之封装

点击返回标题->23年Java期末复习-CSDN博客 第1题. 定义一个类Person,定义name和age私有属性,定义有参的构造方法对name和age进行初始化。在测试类中创建该类的2个对象,姓名、年龄分别为lili、19和lucy、20,在屏幕打印出2个对象的姓名和年龄…

【Lidar】基于Python的三维点云数据转二维平面+散点图绘制

最近一直在搞点云相关的操作,有时候在处理点云数据时需要查看处理后的数据是否满足需求,所以就想着写一套展示点云的代码。之前已经分享过如何可视化点云了,感兴趣的可以自己去看下:【Lidar】基于Python的Open3D库可视化点云数据。…

微信商城小程序怎么弄

随着移动互联网的快速发展,微信小程序已经成为了许多商家和企业拓展业务的新渠道。其中,微信商城小程序更是受到了广大用户的喜爱。那么微信商城小程序怎么弄呢?下面给大家做个详细讲解。 首先,你需要在微信公众平台注册一个小程…

孩子都能学会的FPGA:第二十三课——用FPGA实现格雷码的编码和解码

(原创声明:该文是作者的原创,面向对象是FPGA入门者,后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门,作者不光让大家知其然,还要让大家知其所以然!每个工程作者都搭建了全自动化的仿…

文心一言大模型应用开发入门

本文重点介绍百度智能云平台、文心一言、千帆大模型平台的基本使用与接入流程及其详细步骤。 注册文心一言 请登录文心一言官方网站 https://yiyan.baidu.com/welcome 点击登录;图示如下: 请注册文心一言账号并点击登录,图示如下&#xff1…

深入理解数据在内存中是如何存储的,位移操作符如何使用(能看懂文字就能明白系列)文章超长,慢慢品尝

系列文章目录 C语言笔记专栏 能看懂文字就能明白系列 🌟 个人主页:古德猫宁- 🌈 信念如阳光,照亮前行的每一步 文章目录 系列文章目录🌈 *信念如阳光,照亮前行的每一步* 前言引子一、2进制和进制转化为什么…

ORACLE数据库实验总集 实验四 Oracle数据库物理存储结构管理

一、实验目的 (1)掌握 Oracle数据库数据文件的管理 (2)掌握 Oracle数据库控制文件的管理 (3)掌握 Oracle数据库重做日志文件的管理 (4)掌握 Oracle数据库归档管理, 二、…

Golang 原生Rpc Server实现

Golang 原生Rpc Server实现 引言源码解析服务端数据结构服务注册请求处理 客户端数据结构建立连接请求调用 延伸异步调用定制服务名采用TPC协议建立连接自定义编码格式自定义服务器 参考 引言 本文我们来看看golang原生rpc库的实现 , 首先来看一下golang rpc库的demo案例: 服…

忘记PDF密码了,怎么办?

PDF文件有两种密码,一个打开密码、一个限制编辑密码,因为PDF文件设置了密码,那么打开、编辑PDF文件就会受到限制。忘记了PDF密码该如何解密? PDF和office一样,可以对文件进行加密,但是没有提供恢复密码的功…

动态代理IP和静态代理IP有什么区别,适用场景是什么?

互联网行业的从业者经常会用到一种工具,那就是代理IP工具。动态代理IP和静态代理IP是两种常见的代理IP技术,它们在网络通信中起到了重要的作用,比如大数据行业的从业者会经常需要用到动态代理IP,跨境行业的从业者会经常用到静态代…

MySQL 忘记root密码后重置密码操作

在忘记 MySQL 密码的情况下,可以通过 --skip-grant-tables 关闭服务器的认证,然后重置 root 的密码,具体操作步骤如下。 步骤 1):关闭正在运行的 MySQL 服务。打开 cmd 进入 MySQL 的 bin 目录。 步骤 2):输入mysqld -…

Constraining Async Clock Domain Crossing

Constraining Async Clock Domain Crossing 我们在normal STA中只会去check 同步clock之间的timing,但是design中往往会存在很多CDC paths,这些paths需要被正确约束才能保证design function正确,那么怎么去约束这些CDC paths呢? 以下面的design为例,如下图所示 这里clk…

基于Linux的网络防火墙设计方法

摘要 随着Internet的迅速发展,网络越来越成为了人们日常生活不可或缺的一部分,而随之引出的网络安全问题也越来越突出,成为人们不得不关注的问题。 为了在一个不安全的网际环境中构造出一个相对安全的环境,保证子网环境下的计算机…

lorenz相图

观察Lorenz在各个不同维度上的相图。 lorenz_demo(50) function xdot g(t,x) xdot zeros(3,1); sig 10.0; rho 28.0; bet 8.0/3.0; xdot(1) sig*(x(2)-x(1)); xdot(2) rho*x(1)-x(2)-x(1)*x(3); xdot(3) x(1)*x(2)-bet*x(3); endfunction lorenz_demo(time) [t,x] ode…