单接口的批量测试如何实现

news2024/12/23 11:04:05

一、痛点:一条测试数据对应一个测试方法

前面的章节中我们已经写代码实现了登录接口的处理调用,但是一个接口往往是需要多条测试用例才能完整的覆盖到每一种情况,针对于单接口多条测试用例需要执行的情况,该如何处理呢,可能很多人最先想到的就是:一条测试数据对应一个测试方法?下面有一个注册接口,我们基于此思路来编码实现接口的完整测试。

1) 接口业务:会员注册

2) 接口地址:https://www.bilibili.com/video/BV1w3411q7BP/

3) 接口参数:mobilephone+pwd

4) 接口响应:json格式的报文

  关于这个接口的更多详细的细节我们可以从公司提供的接口文档中获取,在公司里面做接口项目的测试,不管是自动化测试还是非自动化,都会有这样的一个文档描述接口项目中的每一个接口的细节,包括业务,接口地址,参数,响应报文中的字段以及格式,这是我们在测试前编写测试用例的重要参考文献,大部分接口文档的撰写都大同小异,关于接口的一些重要信息一般都会涵盖到,比如以下接口文档关于注册接口的描述:

现在我们整理得到一条正向用例和几条反向用例:

1.合格手机号,合格密码

2.重复以上的手机号,密码

3.传手机号,不传密码

4.不传手机号,传密码

5.不合格的手机号

6.合格的手机号,不合格密码

  编写测试类,每条用例,准备一个测试方法:test1-test6对应上面每种测试情况:  test1方法(mobilephone:18999700122;pwd:123456):


    @Test
    public void test1(){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.创建post对象,以post方式提交接口请求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.准备提交参数
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", "18999700122");
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", "123456");
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.参数封装到请求体当中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.准备客户端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交请求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回数据,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
            //7.输出结果到控制台验证数据
            System.out.println("*********返回数据:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

test2方法(mobilephone:18999700122;pwd:123456)


    @Test
    public void test1(){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.创建post对象,以post方式提交接口请求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.准备提交参数
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", "18999700122");
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", "123456");
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.参数封装到请求体当中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.准备客户端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交请求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回数据,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
            //7.输出结果到控制台验证数据
            System.out.println("*********返回数据:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

test3方法(mobilephone:18999700122;pwd:空)

@Test
    public void test3(){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.创建post对象,以post方式提交接口请求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.准备提交参数
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", "18999700122");
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", "");
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.参数封装到请求体当中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.准备客户端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交请求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回数据,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
        //7.输出结果到控制台验证数据
            System.out.println("*********返回数据:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

test4方法(mobilephone:空;password:123456)

  @Test
    public void test3(){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.创建post对象,以post方式提交接口请求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.准备提交参数
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", "");
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", "123456");
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.参数封装到请求体当中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.准备客户端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交请求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回数据,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
            //7.输出结果到控制台验证数据
            System.out.println("*********返回数据:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

test5方法(mobilephone:189;password:123456)

   @Test
    public void test3(){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.创建post对象,以post方式提交接口请求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.准备提交参数
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", "189");
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", "123456");
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.参数封装到请求体当中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.准备客户端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交请求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回数据,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
            //7.输出结果到控制台验证数据
            System.out.println("*********返回数据:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

test6(mobilephone:18999700122;password:123456789)

 @Test
    public void test3(){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.创建post对象,以post方式提交接口请求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.准备提交参数
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", "18999700122");
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", "123456789");
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.参数封装到请求体当中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.准备客户端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交请求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回数据,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
            //7.输出结果到控制台验证数据
            System.out.println("*********返回数据:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

执行完毕,我们可以看到六个测试方法都有响应数据返回。

说明这种设计是可以达到我们的目的,但是问题是什么?

我们看到每个方法的代码几乎是一模一样,除了测试数据。目前我们只设计了六条用例,试想,如果有七组,八组,九组...更多组的测试数据,那么将会有更多的重复代码,这样的设计简直就是灾难性的。

二、痛点解决

  上面已经将问题抛出,我们该如何去解决这个问题呢?

  第一种办法是我们自己去编码实现一条解决方案,但是成本太高,而且可能写出来的框架有很多问题。

  第二种办法就是去找一些第三方的框架来帮助我们来解决这个问题,而testng正式我们想要找的这样一个框架,testng的数据提供者技术就能帮我们优雅的解决这个痛点,我们准备一个测试方法就可以了。

测试方法代码:

@Test(dataprrovider=”datas”)
    public void test(String mobilephone,String pwd){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.创建post对象,以post方式提交接口请求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.准备提交参数
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", mobilephone);
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", pwd);
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.参数封装到请求体当中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.准备客户端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交请求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回数据,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
            //7.输出结果到控制台验证数据
            System.out.println("*********返回数据:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

代码改动:

1) 测试方法上多了两个参数

 

2) 代码中直接绑定参数

 

数据提供者代码:

① 数据提供者的作用就是提供几组测试数据给测试方法,方法的返回值必须是二维数组,并且此方法要用@DataProvider来标注:

 

② 测试方法如果要引用数据提供者则必须指定数据提供者的名字:

测试用例执行结果为:

总结:

  对于同一接口的批量测试,变动的数据可能就只有测试数据,因此,我们我们可以考虑通过@Dataprovider来提供几组测试数据,测试方法引用了dataprovider后就能拿到数据,依次注入完成批量测试,从而简化代码,简化测试。

三、 思路延伸

  数据提供者能依次提供测试数据的功能固然很好,但是我们需要的这些测试数据来自于哪里呢。像上面那样直接定义在代码当中,其实属于硬编码的情况,耦合性很高,一旦我们要修改测试数据,那么我们就必须修改代码,而频繁的修改代码就可能导致各种不可预期的问题,要实现一个好的自动化测试框架应该尽可能保证代码的健壮性和兼容性。

那么问题来了,数据源的问题怎么解决?

2023最新Jmeter接口测试从入门到精通(全套项目实战教程)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uboot移植之mx6ull_alientek_nand.h文件详解一

一. 简介 mx6ull_alientek_nand.h文件是 开发板的 uboot的一个配置文件。每个开发板都有一个 .h的配置文件。 mx6ull_alientek_nand.h文件其实是 之前针对正点原子ALPHA开发板移植的 Uboot配置文件。 本文简单分析一下 针对正点原子ALPHA开发板的 配置文件&#xff1a; mx6u…

STL模拟实现—vector

引言&#xff1a;本篇文章主要是模拟实现vector&#xff0c;但不同于stl中vector的成员变量都是迭代器&#xff0c;这个自定义的vector是一个T* 的数据变量和一个int类型的size和int类型的capacity。&#xff08;有时间再写三个迭代器的版本吧&#xff01;&#xff09; 首先来看…

Redis学习(第八章缓存策略)

目录 RdisExample 课程介绍 1.Redis介绍 2.Redis 安装 3. Redis的数据结构 4. Redis缓存特性 5. Redis使用场景 6. Redis客户端-Jedis 7. Jedis Pipeline 8. Redis缓存策略 学习资料 QA 相关问题 http, socket ,tcp的区别 RdisExample 项目代码地址&#xff1a;htt…

Leetcode—104.二叉树的最大深度【简单】

2023每日刷题&#xff08;六&#xff09; Leetcode—104.二叉树的最大深度 递归实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/int maxDepth(struct TreeNode* root){…

2017年高热度编程语言简介

世上语言千千万&#xff0c;我却独爱这一种!”这句话用来形容程序员和编程语言之间的爱恨情仇实在是再精准不过了。根据GitHub 2016年的开源报告&#xff0c;其上所有开源项目共包含了316种编程语言&#xff0c;这是一个什么概念呢?举个例子来说&#xff0c;世界上共有226个国…

高防CDN的发展趋势

随着互联网的迅速发展&#xff0c;网站和在线服务的安全性变得至关重要。网络攻击如DDoS攻击和恶意流量正在增加&#xff0c;因此高防CDN&#xff08;高防御内容分发网络&#xff09;成为网络安全的重要组成部分。本文将探讨高防CDN未来的发展趋势&#xff0c;并比较其与传统CD…

PyCharm改变代码背景图片的使用教程

一个好的集成环境是学习和使用一门编程语言的重中之重&#xff0c;这次我给大家分享如何改变PyCharm软件的代码背景图片。 说明&#xff1a;本教程使用的是汉化版PyCharm软件。 打开PyCharm软件。 点击软件最上方导航栏的文件&#xff0c;然后找到设置。 打开设置然后点击外观…

小米妙享无法正常启动,用非管理员权限启动

网上找到的其他方法大多数不太好 1.非管理员方式运行的方法 1.创建一个用户123&#xff0c;密码123 2.创建一个bat文件&#xff0c;复制粘贴以下内容 runas /savecred /user:123 “C:\Program Files\MI\AIoT\Launch.exe” 第一次点击运行&#xff0c;要输入密码&#xff0c;以…

面试官:说说webpack的热更新是如何做到的?

一、是什么 HMR 全称 Hot Module Replacement&#xff0c;可以理解为模块热替换&#xff0c;指在应用程序运行过程中&#xff0c;替换、添加、删除模块&#xff0c;而无需重新刷新整个应用 例如&#xff0c;我们在应用运行过程中修改了某个模块&#xff0c;通过自动刷新会导致…

靶机 DC_1

DC_1 信息搜集 存活检测 详细扫描 网页目录扫描 网页信息搜集 cms 为 Drupal 漏洞利用 使用 msf 搜索 drupal 的漏洞 启动 msfconsole搜索 search drupal尝试编号为 0 的漏洞 失败 利用编号为 1 的漏洞 use 1查看需要配置的选项 show options设置目标 ip set rhost 10…

Leetcode—1726.同积元组【中等】

2023每日刷题&#xff08;六&#xff09; Leetcode—1726.同积元组 哈希表解题思路 实现代码 class Solution { public:int tupleSameProduct(vector<int>& nums) {unordered_map<int, int>count;int n nums.size();int i, j;for(i 0; i < n - 1; i) {f…

C语言实现单链表(图解增删查改+代码)

文章目录 写在前面1. 链表节点的定义2. 链表的创建3. 插入数据3.1 头插3.2 尾插3.3 在指定位置的前面插入数据 4. 删除数据4.1 头删4.2 尾删4.3 删除指定位置的数据 5. 查找数据5. 链表的销毁 写在前面 上面文章用C语言实现了顺序表的增删查改&#xff0c;本片文章继续用C语言…

web各个指标理解

QPS : 单位时间得请求次数 TPS &#xff1a;单位时间得事务数 并发 &#xff1a; QPS *单位响应时间 pv &#xff1a;进入一个网站&#xff0c;又单击打开该网站的其他页面&#xff0c;每打开一个页面就 增加一个PV,甚至在同一页面每刷新一次也多一个PV 二八定律&#xff1a;百…

nonaDlA 逻辑分析仪 使用记录

注意事项&#xff0c;很灵敏&#xff0c;不要用手碰&#xff0c;产生误触发 安装软件 github地址 官方提供的淘宝地址与使用说明 1.安装 1.安装程序 &#xff1a;下载githubDLA源码&#xff0c;打开 software\PulseView.exe安装 2.安装驱动&#xff1a;安装完第一步后&a…

【OpenVINO】行人摔倒检测 — 基于 OpenVINO C# API 部署PP-Human-下篇

行人摔倒检测 — 基于 OpenVINO C# API 部署PP-Human 4. 配置 PP-Human_Fall_Detection 项目4.1 环境配置4.2 创建 AlxBoard_deploy_yolov8 项目4.3 添加项目源码4.4 添加 OpenVINO C# API4.5 添加 OpenCvSharp 5. 测试 PP-Human_Fall_Detection 项目5.1 创建视频读取器5.2 行人…

Python南瓜头

系列文章 ​​​​​​​ 序号文章目录直达链接1浪漫520表白代码https://want595.blog.csdn.net/article/details/1306668812满屏表白代码https://want595.blog.csdn.net/article/details/1297945183跳动的爱心https://want595.blog.csdn.net/article/details/1295031234漂浮…

生成二维码

Qt本地生成二维码-第三方库Libqrencode Chapter1 Qt本地生成二维码-第三方库Libqrencode一、功能简介二、本地生成二维码三、在线生成二维码 Chapter2 Qt生成二维码图片方法QRCode二维码简介如何选定QR码版本&#xff1f;主要方法(1) 下载qrencode源码(2) 将qrencode源码移植到…

C++ STL六大组件

目录 前言 一、容器 1 向量 1.1 向量&#xff08;Vector&#xff09;和数组&#xff08;array&#xff09;之间的区别 1.2 语法 1.3 示例 1.3.1 创建 vector 对象 1.3.2 不能打印向量对象&#xff1b;不能打印空向量中的元素&#xff0c;因为空向量中无元素可打印 1.3…

又哭又笑,这份面试宝典要是早遇到就好了

01、算法原理 选择排序(Selection sort)是一种简单直观的排序算法。 第一次从待排序的数据元素中选出最小&#xff08;或最大&#xff09;的一个元素&#xff0c;存放在序列的起始位置&#xff0c;然后再从剩余的未排序元素中寻找到最小&#xff08;大&#xff09;元素&#…

filebeat(8.9.0)采集日志到logstash,由logstash发送的es

filebeat采集日志到logstash&#xff0c;由logstash发送的es 下载并配置filebeat下载配置logback.xml logstash配置 下载并配置filebeat 下载 参考 配置 filebeat.inputs: - type: filestreamenabled: truepaths:# 日志文件目录- D:\modellog\elkdemo\*\*.logparsers:# 多…