基于Java+HttpClient+TestNG的接口自动化测试框架(四)-------参数存取处理

  在真正开始接口测试之前,我们需要对参数的处理进行梳理。这里所说的“参数”,既包含之前在xml中的配置(我们称之为全局参数),也包含在每一条用例中书写的param。全局参数为固定不变的,而根据接口相应获取的数据是动态变化的。

  之前我们已经用${param_name}的形式,定义了如何从公共参数池中调用所需要的参数。

并且当一个接口的请求发送完成,进行下一个接口操作的时候,我们也需要对相应的数据进行处理。例如,前面一个接口的响应中出现了下一个接口需要使用的数据,比如id,password,token等等。那么需要对这些数值进行操作(保存·),把获取到的数据存入这个公共参数池中,然后在后续的接口请求中调用这些数据。

  对于作为测试用例数据的格式,我们可以把它设计成这样的。

在这里,我们可以看到,在url,header,param中,我们使用了${param_name}的形式,这些变量可以从我们的公共参数池中取得,而后面的verify,可以对返回值使用JSONPath来精准判定。而对于,save中的内容,我们可以将其存入公共参数池,供后面的接口进行调用。

  接下来,我们逐步来作成TestBase的基础类,在这个类中,我们来逐步定义如何处理参数以及如何来使用参数。在这个类中,牵涉到很多关联调用的其他工具类,在本篇中暂时不做说明。在之后的章节中来逐步去说明调用关系。

  PS:在我们写一个程序时,如果一时不能把程序的构造想清楚,可以先用自然语言把整体逻辑描述清楚,具体的代码可以之后再进行斟酌。

  首先,我们先需要定义一个公共参数池,以及对应与${param_name}的正则表达式。

 

    /**
     * 公共参数数据池(全局可用)
     */
    private static Map<String, String> saveDatas = new HashMap<String, String>();

    /**
     * 替换符,如果数据中包含“${}”则会被替换成公共参数中存储的数据
     */
    protected Pattern replaceParamPattern = Pattern.compile("\\$\\{(.*?)\\}");

    /**
     * 获取公共数据池中的数据
     *
     * @param key
     *            公共数据的key
     * @return 对应的value
     */
    protected String getSaveData(String key) {
        if ("".equals(key) || !saveDatas.containsKey(key)) {
            return null;
        } else {
            return saveDatas.get(key);
        }
    }
    protected void setSaveDatas(Map<String, String> map) {
        saveDatas.putAll(map);
    }

  在使用过程中,我们可以将参数分为两类。第一类为全局参数,意思是可以将之前从xml中读取的配置,作为全局参数存入公共参数数据池,在整个接口测试运行的过程中均可进行调用。第二类是,接口过程中产生对的过程参数,即,接口A返回的数据,可以作为参数使用在接口B的请求中。这类参数在接口请求执行过程中进行定义,也存入公共参数池。

  这两类参数,均使用${param_name}的形式进行调用。来看下面一段代码:

    /**
     * 取公共参数 并替换参数,处理${}
     * @param param
     * @return
     */
    protected String getCommonParam(String param) {
        if (stringUtil.isEmpty(param)) {     //stringUtil后续进行说明
            return "";
        }
        Matcher m = replaceParamPattern.matcher(param);// 取公共参数正则
        while (m.find()) {
            String replaceKey = m.group(1);
            // 如果公共参数池中未能找到对应的值,该用例失败。
            Assert.assertNotNull(replaceKey,
                    String.format("格式化参数失败,公共参数中找不到%s。", replaceKey));
            String value;
            // 从公共参数池中获取值
            value = getSaveData(replaceKey);
            //如果值不为空,则将参数替换为公共参数池里读取到的value的值。
            if(null != value) {
                param = param.replace(m.group(), value);
                //如果值为空,则将参数替换为字符串“null”
            }else {
                param = param.replace(m.group(), "null");
            }
        }
        return param;
    }

  这里使用了正则表达式来匹配参数中出现的${XXXX}形式的字符串。这一段的主要思想为,使用定义好的正则表达式来匹配param的字符串,如果匹配的到,则进行循环,把匹配到的第一个字符串(基本就是1个字符串)作为key,然后到saveData的Map中取得对应的值,并返回。

  这样,我们就实现了使用${param_name}的形式,调用公共参数池的目的。

  那么说完了“取参数”,我们还需要说一下“存参数”。在接口测试执行的过程中,假如我想把某个返回的值作为参数,存入公共参数池中,我们应该怎么做呢?

    /**
     * 提取json串中的值保存至公共池中
     *
     * @param json
     *            将被提取的json串。
     * @param allSave
     *            所有将被保存的数据:xx=$.jsonpath.xx;将$.jsonpath.
     *            xx提取出来的值存放至公共池的xx中
     */
    protected void saveResult(String json, String allSave) {
        if (null == json || "".equals(json) || null == allSave
                || "".equals(allSave)) {
            return;
        }
        allSave = getCommonParam(allSave);
        String[] saves = allSave.split(";");
        String key, value;
        for (String save : saves) {
            Pattern pattern = Pattern.compile("([^;=]*)=([^;]*)");
            Matcher m = pattern.matcher(save.trim());
            while (m.find()) {
                key = getBuildValue(json, m.group(1));  //getBuildValue的方法后续说明
                value = getBuildValue(json, m.group(2));
                reportUtil.log(String.format("存储公共参数   %s值为:%s.", key, value));
                saveDatas.put(key, value);
            }
        }
    }

  这里我们在save时,同样是通过正则表达式来进行匹配,具体的形式类似于 aa=$.Content.User 的形式,即变量名=JSONPath,将JSONPath找到的值来赋此变量,并存储到公共参数池中。

  这里提到了一个getBuildValue的方法,具体的代码如下:

/**
     * 获取格式化后的值
     *
     * @param sourchJson
     * @param key
     * @return
     */
    private String getBuildValue(String sourchJson, String key) {
        key = key.trim();
        Matcher funMatch = funPattern.matcher(key); //funPattern为函数匹配正则表达式,后续进行说明
        if (key.startsWith("$.")) {// 如果为JSONPath,获取该JSONPath对应的值(对象)
            Object x = JSONPath.read(sourchJson, key);       //空值处理
            if(x == null) {
                key = (String)x;
            }else {
                key = x.toString();
            }       //如果匹配到的是自定义函数,则先解析该自定义函数的参数,若该自定义函数的参数中有JSONPath,则对该JSONPath取值,并对应转成字符串对象。
        } else if (funMatch.find()) {
            String args = funMatch.group(2);
            String[] argArr = args.split(",");
            for (int index = 0; index < argArr.length; index++) {
                String arg = argArr[index];
                if (arg.startsWith("$.")) {
                    argArr[index] = JSONPath.read(sourchJson, arg).toString();
                }
            }
            String value = functionUtil.getValue(funMatch.group(1), argArr); // functionUtil为自定义函数工具类,后续说明
            key = stringUtil.replaceFirst(key, funMatch.group(), value);
        }
        return key;
    }

  那么,通过以上的代码,我们可以较为清晰的看到,我们设计了这个公共参数池,来对全局参数和过程参数进行管理,即可取也可存。方便了在之后的代码中进行调用。

  在上面的代码中,我们出现了一个stringUtil的工具类,这算是一个字符串处理工具。请看以下代码:

public class stringUtil {
    public static boolean isNotEmpty(String str) {
        return null != str && !"".equals(str);
    }

    public static boolean isEmpty(String str) {
        return null == str || "".equals(str);
    }

    /**
     *
     * @param sourceStr 待替换字符串
     * @param matchStr  匹配字符串
     * @param replaceStr  目标替换字符串
     * @return
     */
    public static String replaceFirst(String sourceStr,String matchStr,String replaceStr){
        int index = sourceStr.indexOf(matchStr);
        int matLength = matchStr.length();
        int sourLength = sourceStr.length();
        String beginStr = sourceStr.substring(0,index);
        String endStr = sourceStr.substring(index+matLength,sourLength);
        sourceStr = beginStr + replaceStr + endStr;
        return sourceStr;
    }

}

  这个工具类中,写了判定字符串是否为空的方法,还有一个替换首个匹配字符串的方法。有兴趣的童鞋可以自行继续扩展。

  

  

原文地址:https://www.cnblogs.com/generalli2019/p/12212591.html

时间: 2024-07-31 12:29:24

基于Java+HttpClient+TestNG的接口自动化测试框架(四)-------参数存取处理的相关文章

基于Java+HttpClient+TestNG的接口自动化测试框架(五)------ 测试用函数接口类及实现类

在前一篇中,我们着重阐述了参数的处理方法. 但是,这些参数基本都是直接赋值的.而实际的接口测试中,我们会根据需要做成很多的测试数据,这些测试数据会根据不同的情况来使用.例如,我可能需要一个能够随机生成一个中文的字符串,或者需要一个能够迅速求出一个文件或者字符串的MD5的值.在这种情况下,就需要我们动手去写一些函数来进行调用. 不过,如果是在Excel(或者其他文本编辑器)中写测试用例,如何才能让程序能够知道我是在调用一个函数,并且能够把这个函数的返回值赋给变量,正确的传入我想要的地方呢?下面,我

基于Java+HttpClient+TestNG的接口自动化测试框架(六)-------随机函数的处理

我们之前使用接口类及接口实现类的方式,来定义了我们使用的工具类. 而所有的工具类中,随机函数是比较难于处理的.因为随机的对象不明确,随机的个数不明确.我们可以使用定义随机类的方式,来简单而快速的处理我们的随机对象生成的需要. 首先,我们先定义一个randomUtil的类,在这个类中,我们可以将想生成的随机函数进行具体的定义.在此,我们举几个例子.比如,随机生成一个整数,随机生成一个定长(或不定长)的,带汉字(或不带汉字)的字符串,随机生成一个数组等等. 来看一下具体的RandomUtil类的代码

基于Java+HttpClient+TestNG的接口自动化测试框架(八)------ 针对文件的处理

在实际的接口测试中,有时需要根据情况进行文件的上传和下载.在文件数量比较小的时候,我们当然可以直接处理(比如若干个接口都用一个文件).但是,如果我们上传的文件需要使用不同文件夹里不同的文件,而且数量又比较大的情况下,直接写路径就比较麻烦了. 那么,怎样来处理这样的问题呢?还是需要先整理一下思路. 首先,我们需要根据某些特征,找到这些文件.例如,我们可以在指定的文件夹下面,按照文件后缀名来找寻文件.通常,我们在DOS下查询该文件夹下寻找同一后缀名文件的时候,会使用通配符“*”来代替文件名,例如:*

手把手教你用Eclipse+TestNG搭建接口自动化测试框架

转载于:http://qa.blog.163.com/blog/static/190147002201510275306185/ 把群博里关于接口自动化的文章都看了一遍,都是关于测试过程中遇到的问题及解决方法,还没有框架搭建的博文.对于未做过接口自动化和java菜鸟的我,搭建好框架才是迈出的第一步.记录下搭建的过程,希望能够对想做接口自动化的同志们有一定的帮助.有些步骤较粗,若有问题,欢迎联系我. 一.环境安装 1.前提 安装好jdk 配置好Java环境变量 安装Eclips 这些网上都有,就不

Eclipse+TestNG搭建接口自动化测试框架

一.环境安装 1.前提 安装好jdk 配置好Java环境变量 安装Eclips 这些网上都有,就不再详细介绍. 资源分享链接:http://pan.baidu.com/s/1v9Fw6 2.安装TestNG插件 在线安装由于网速原因,速度较慢.下面是离线安装方式. (1)解压eclipse-testng离线包.zip (2)将[eclipse-testng离线包/feature]中的文件夹org.testng.eclipse_6.8.6.20130607_0745复制到[MyEclipse安装目

Python 基于python实现的http+json协议接口自动化测试框架源码(实用改进版)

目录 1.      写在前面 2.      开发环境 3.      大致流程 4.      框架简介 5.      运行结果展示 6.      文件与配置 7.      测试接口实例 n      1.登陆接口 n      2.支付密码更改接口 8.      数据库设计 9.      测试用例.测试数据准备 10.        模块与类.函数设计 11.        代码实现 a)         class congfighttp.ConfigHttp b)      

接口自动化测试框架 -- reudom

reudom Automated testing framework based on requests and unittest interface. 基于 Unittest 和 Requests 的 接口自动化测试框架 介绍 基于Unittest/Requests的接口自动化测试库 提供脚手架,快速生成接口自动化测试项目. 自动生成HTML测试报告. 支持用例参数化. 支持用例失败重跑 对原生Requests库API无损 目录架构 myreudom/ ├── test_case/ │ ├──

基于Python接口自动化测试框架(初级篇)附源码

引言 很多人都知道,目前市场上很多自动化测试工具,比如:Jmeter,Postman,TestLink等,还有一些自动化测试平台,那为啥还要开发接口自动化测试框架呢?相同之处就不说了,先说一下工具的局限性: 1.测试数据不可控:    接口虽然是对业务逻辑.程序代码的测试,而实际上是对数据的测试,调用接口输入一批数据,通过断言代码验证接口返回的数据,整个过程围绕数据测试.    如果返回的数据不是固定的,是变化的,那么断言失败,就无法知道是接口程序错误引起的,还是数据变化引起的,所以就需要进行测

构建接口自动化测试框架

背景 由于项目需要实现接口自动化,于是我自己用Java + testNG 实现了一套接口自动化测试框架.基本功能实现了测试数据的读取,接口的请求,返回值的处理以及最后的断言. 先来看一下框架的目录结构: 框架比较简单,在设置好测试数据之后,就可以开始写用例了,如: 是不是很方便,用例写好之后,就可以部署Jenkins自动执行了. 下面来具体看一下框架的实现 测试数据的存储和读取 测试数据存在在TestData下的xml文件,每条用例一个文件,然后通过XML类去读取文件内容,并将内容转换成json