模拟测试环境实现随机造数功能

背景:需要实现如下功能

1,提供自动测试接口功能,每天运行

2,随机生成数据组成请求参数请求各个接口(某些参数必须要从数据库读取,随机生成无法实现)

3,提供页面,实现只输入json字符串,系统,请求服务ID,请求类型,便能够请求各类接口

4,页面请求的参数如果与测试用例的参数一致,返回测试用例的预测结果以及接口返回的结果,不一致,便单独返回接口的请求结果

5,页面能够自动把json数据格式化以及把测试用例的结果与接口返回结果进行对比

==============================================================================

由于之前在服务器上搭建了jenkins+tomcat+zookeeper+dubbo的环境,现已经部署了所有的线上运行项目,由此有如下思路

思路:

1,需要单独部署一个独立项目

2,独立项目提供页面输入请求参数

3,需要提供定时任务

4,需要随机生成数据

5,需要连接数据库

基于此采取如下方案

方案:

1,选用springboot+mybatis+oracle+druid(如果需要再增加redis作为缓存)

2,前端采用html+css+js+jquery+bootstrap3+ajax(页面没有实现自适应)

===============================================================================

前端页面样式

 

 

备注:此为一个页面

============================================================================================

页面代码:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>Jfpointscore-Test</title>

    <!-- Bootstrap -->
    <link href="css/bootstrap.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">
    <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
    <script src="js/jquery-1.10.1.js"></script>
    <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
    <script src="js/bootstrap.js"></script>
    <script src="js/index.js"></script>
  </head>
  <body>
      <!--容器  -->
    <div class="container">
        <div class="page-header">
              <h1>Compare Json<small></small></h1>
        </div>
        <div id="request_container" class="jumbotron">
            <h4 id="tip_font" class="tip_font">请输入Json数据</h4>
              <textarea id="input_content" class="request_content"></textarea>

              <div class="request_container_bottom">
                  <!--格式化按钮  -->
                <div id="format_button" class="btn-group format_button" role="group" aria-label="...">
                    <button id="format_json" type="button" class="btn btn-default" onclick="click_format_json();">格式化</button>
                </div>
                <!--系统按钮  -->
                <div class="blank_button btn">
                     System:
                </div>
                <div id="system_button" class="dropdown system_button">
                     <button class="btn btn-default dropdown-toggle" type="button" id="system_type" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" value="">
                        请选择请求应用
                            <span class="caret"></span>
                      </button>
                      <ul class="dropdown-menu" aria-labelledby="system_type">
                            <li><a href="javascript:void(0)" id="system_jfpointscore-service" onclick='get_system("jfpointscore-service");'>jfpointscore-service</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="javascript:void(0)"    id="system_jfpointscoreqry-service" onclick='get_system("jfpointscoreqry-service");'>jfpointscoreqry-service</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="javascript:void(0)"    id="system_jfpointscore-job" onclick='get_system("jfpointscore-job");'>jfpointscore-job</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="javascript:void(0)"    id="system_jfpointssettle-job" onclick='get_system("jfpointssettle-job");'>jfpointssettle-job</a></li>
                      </ul>
                </div>
                <div class="blank_button btn">
                    RequestType:
                </div>
                <!--请求类型按钮  -->
                <div id="request_button" class="dropdown request_button">
                      <button class="btn btn-default dropdown-toggle request_button_button" type="button" id="request_type" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" value="">
                        请选择请求类型
                            <span class="caret"></span>
                      </button>
                      <ul class="dropdown-menu" aria-labelledby="request_type">
                            <li><a href="javascript:void(0)" id="system_jfpointscore-service" onclick='get_request_type("biz");'>biz</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="javascript:void(0)"    id="system_jfpointscoreqry-service" onclick='get_request_type("dubbo");'>dubbo</a></li>
                           <!--  <li><a href="#" onclick='get_system("none");'>reset</a></li> -->
                      </ul>
                </div>
                <div class="blank_button btn">
                    ServiceId:
                </div>
                <!--serviceId  -->
                <div class="form-group service_id" id="service_id">
                    <input id="serviceId" type="text" class="form-control" placeholder="ServiceId">
                  </div>

                  <!--格式化按钮  -->
                <div id="submit_button" class="btn-group submit_button" role="group" aria-label="...">
                    <button id="submit_request" type="button" class="btn btn-default" onclick="submit_request();">提交</button>
                </div>

            </div>
        </div>

        <div id="response_container" class="jumbotron response_container">
            <div id="response_container_left" class="response_container_left">
                <h4 id="tip_font_response" class="tip_font_response">测试用例参数</h4>
                <textarea id="out_content_left" class="response_content_left" readonly="readonly"></textarea>
            </div>

            <div id="response_container_middle" class="response_container_middle">
                <!--格式化按钮  -->
                <div id="response_format_button" class="btn-group response_format_button" role="group" aria-label="...">
                    <button id="response_format_json" type="button" class="btn btn-default response_format_json " onclick="format_result();">格式化</button>
                </div>
            </div>


            <div id="response_container_right" class="response_container_right">
                <h4 id="tip_font_response" class="tip_font_response">系统返回参数</h4>
                <textarea id="out_content_right" class="response_content_right" readonly="readonly"></textarea>
            </div>

              <!--格式化按钮  -->
            <div id="backup_format_button" class="btn-group backup_response_format_json" role="group" aria-label="...">
                <button id="backup_response_format_json" type="button" class="btn btn-default" onclick="format_result();">格式化</button>
            </div>
        </div>

    </div>
  </body>
</html>


=====================================================================

js代码:

//监听textarea的内容
window.onload = function () {
       //获取文本内容和长度函数
        function txtCount(el) {
            var val = el.value;
            var eLen = val.length;
            return eLen;
        }
        var content = "请输入Json数据";
        var el = document.getElementById('input_content');
        el.addEventListener('input',function () {
            var len =  txtCount(this); //   调用函数
            if(len == 0){
                document.getElementById('tip_font').innerHTML = content;
                $("#tip_font").css("color","black");
            }
        });

        el.addEventListener('propertychange',function () {//兼容IE
            var len =  txtCount(this); //   调用函数
            if(len == 0){
                document.getElementById('tip_font').innerHTML = content;
                $("#tip_font").css("color","black");
            }

        });

//        $("#out_content_left").text("2222222");
//        $("#out_content_right").text("11111111");
}


/*格式化json数据*/
function formatJson(){
    var flag = false;
    var text = $("#input_content").val(); //获取json格式内容
    var result = text;
    if(is_json(text)){
        result = JSON.stringify(JSON.parse(text), null, 4);//将字符串转换成json对象
        $("#tip_font").text("Json数据格式正确");
        $("#tip_font").css("color","green");
        flag = true;
    }else{
        $("#tip_font").text("Json数据格式错误");
        $("#tip_font").css("color","red");
    }
    $("#input_content").val(result);
    return flag;
}

/*格式化json内容*/
function click_format_json(){
    formatJson();
}

/*判断是否是json格式*/
function is_json(str) {
    var flag = false;
    if (typeof str == 'string') {
        try {
            var obj = JSON.parse(str);
            if(typeof obj == 'object' && obj ){
                flag = true;
            }else{
                flag = false;
            }
        } catch(e) {
            console.log('error:'+str+'!!!'+e);
            flag = false;
        }
    }else{
        console.log('It is not a string!');
        flag = false;
    }
    return flag;
}

/**获取选择的系统*/
function get_system(systemName){
    console.log("传入的系统为"+systemName);
    //var text = $("#system_"+systemName).html();
    var text = systemName;
    console.log(text);
    $("#system_type").val(systemName);//button里的值
    $("#system_type").text(systemName);

}
/**获取选择的请求类型*/
function get_request_type(requestType){
    console.log("传入的请求类型为"+requestType);
    //var text = $("#system_"+systemName).html();
    var text = requestType;
    console.log(text);
    $("#request_type").val(requestType);
    $("#request_type").text(requestType+"");

}
/**提交按钮*/
function submit_request(){
     var flag = false;

     var json = $("#input_content").val();
     var system = $("#system_type").text();//button显示的内容
     var systemValue = $("#system_type").val();//button里的值
     var requestType = $("#request_type").text();//button显示的内容
     var requestTypeValue = $("#request_type").val();//button里的值
     var serviceId = $("#serviceId").val();
     console.log(json);
     console.log(systemValue);
     console.log(requestTypeValue);
     console.log(serviceId);
     if(json.length == 0 || systemValue.length == 0 || requestTypeValue.length == 0 || serviceId.length == 0){
         $("#tip_font").css("color","red");
         if(json.length == 0){
             $("#tip_font").text("json数据不可以为空!");
             return;
         }else{
             if(is_json()){
                 $("#tip_font").text("");
             }else{
                 $("#tip_font").text("Json数据格式错误");
                 $("#tip_font").css("color","red");
             }
         }
         if(systemValue.length == 0){
             $("#tip_font").text("请求应用不可以为空!");
             return;
         }else{
             $("#tip_font").text("");
         }
         if(requestTypeValue.length == 0){
             $("#tip_font").text("请求类型不可以为空!");
             return;
         }else{
             $("#tip_font").text("");
         }
         if(serviceId.length == 0){
             $("#tip_font").text("serviceId不可以为空!");
             return;
         }else{
             $("#tip_font").text("");
         }
     }

     if(json.length != 0 && systemValue.length != 0 && requestTypeValue.length != 0 && serviceId.length != 0){
         flag = true;
     }

     if(flag){
         if(formatJson()){
             $("#tip_font").css("color","black");

             timer(5);
             //请求后台

             request_admin();

         }
     }

}
/*按钮禁用5秒*/
function timer(time) {
    var btn = $("#submit_request");
    btn.attr("disabled", true);  //按钮禁止点击
    btn.text(time <= 0 ? "时间参数不正确" : ("" + (time) + "秒后可再次请求"));
    var hander = setInterval(function() {
        if (time <= 0) {
            clearInterval(hander); //清除倒计时
            btn.text("提交");
            btn.attr("disabled", false);
            return false;
        }else {
            btn.text("" + (time--) + "秒后可再次请求");
        }
    }, 1000);
}

/*请求后台*/
//后端使用@RequestBody接收请求使用此类
function request_admin(){
    var url = "/jfpointscore-test/action";
    $.ajax({
        type: "post",
        url: url,
        data:JSON.stringify(get_json_data()),
        cache: false,
        async : true,
        dataType: "json",
        contentType: "application/json",
        success: function (data ,textStatus, jqXHR)
        {
            if("success"==data.status){
                console.log("合法!");
                console.log("===============测试用例结果如下==================");
                console.log(JSON.stringify(data.resultTest));
                console.log("===============请求参数结果如下==================");
                console.log(JSON.stringify(data.result));

                display_result_to_test(data.resultTest);
                display_result_to_result(data.result);
                return true;
            }else{
                console.log("不合法!错误信息如下:"+data.errorMsg);
                return false;
            }
        },
        error:function (XMLHttpRequest, textStatus, errorThrown) {
            console.log("请求失败!");
        }
     });
}

/*请求后台*/
//后端如果使用HttpServletRequest接收请求,使用req.getParameter("system")获取参数,就用此类写法
function request_admin_http(){
    var url = "/jfpointscore-test/action";
    var json = $("#input_content").val();
    var system = $("#system_type").text();//button显示的内容
    var systemValue = $("#system_type").val();//button里的值
    var requestType = $("#request_type").text();//button显示的内容
    var requestTypeValue = $("#request_type").val();//button里的值
    var serviceId = $("#serviceId").val();

    $.ajax({
        type: "post",
        url: url,
        data: {"system":systemValue,"requestType":requestTypeValue,"serviceId":serviceId,"json":json},
        cache: false,
        async : true,
        dataType: "json",
        success: function (data ,textStatus, jqXHR)
        {
            if("true"==data.flag){
                console.log("合法!");
                return true;
            }else{
                console.log("不合法!错误信息如下:"+data.errorMsg);
                return false;
            }
        },
        error:function (XMLHttpRequest, textStatus, errorThrown) {
            console.log("请求失败!");
        }
     });
}


/*组装json数据*/
function get_json_data() {
    var json = $("#input_content").val();
    var system = $("#system_type").text();//button显示的内容
    var systemValue = $("#system_type").val();//button里的值
    var requestType = $("#request_type").text();//button显示的内容
    var requestTypeValue = $("#request_type").val();//button里的值
    var serviceId = $("#serviceId").val();

    var jsonResult = {
        "system": systemValue,
        "requestType": requestTypeValue,
        "serviceId": serviceId,
        "json": json
    }
    return jsonResult;
}

//展示测试用例结果
function display_result_to_test(data){
    var result = null;
    if(data == null || data == ""){
        result = "暂无测试用例数据!" ;
    }else{
        result = JSON.stringify(data);
    }
    $("#out_content_left").text(result);
}
//展示请求数据真实返回结果
function display_result_to_result(data){
    var result = null;
    if(data == null || data == ""){
        result = "返回数据异常!" ;
    }else{
        result = JSON.stringify(data);
    }
    $("#out_content_right").text(result);
}

//返回结果格式化
function format_result(){
    var test_result = $("#out_content_left").text();
    var result = $("#out_content_right").text();

    if(test_result != null && test_result != "" && test_result != "暂无测试用例数据!"){
        test_result = JSON.stringify(JSON.parse(test_result), null, 4);//将字符串转换成json对象
    }

    if(result != null && result != "" && result != "返回数据异常!"){
        result = JSON.stringify(JSON.parse(result), null, 4);//将字符串转换成json对象
    }

    $("#out_content_left").text(test_result);
    $("#out_content_right").text(result);
}

============================================================

css代码

/* 容器 */
.container{
    height:1200px;
    color:black;
    /* outline:1px solid black; */
    width:100%;
}
.jumbotron{
    height:40%;
}

/* 请求json内容框 */
.request_content{
    width:100%;
    height:80%;
    color:blue;
}
.request_container_bottom{
    width:100%;
    margin:0 auto;
}

.tip_font{
    color:black;
}
/* 格式化按钮 */
.format_button{
    float:left;

}
/* 系统下拉按钮 */
.system_button{
    float:left;
    margin-left:-10px;
}
/* 请求类型下拉按钮 */
.request_button{
    float:left;
    margin-left:-10px;
}

/*提示  */
.blank_button{
    margin-left:20px;
    float:left;
    text-align:center;
    line-height:20px;
    disabled:disabled;
}
/* ServiceId */
.service_id{
    float:left;
    margin-left:-10px;
    width:30%;
}
/*提交按钮  */
.submit_button{
    float:left;
    margin-left:20px;
}
/************************************/
/*结果返回容器*/
.response_container{
    height:50%;
}
.response_container_left{
    width:45%;
    height:90%;
    /* outline:1px solid black; */
    float:left;

}
.response_container_right{
    width:45%;
    height:90%;
    /* outline:1px solid black; */
    float:left;
}
.response_container_middle{
    float:left;
    width:10%;
    height:100%;
}

.response_content_left{
    width:100%;
    height:100%;
    color:blue;
}

.response_content_right{
    width:100%;
    height:100%;
    color:blue;
}
/*格式化按钮*/
.response_format_button{
    margin:200% 20%;
}

/*备用按钮*/
.backup_response_format_json{
    float:right;
    display:none;
    position:absolute;
    right:5%;
}
textarea:focus{
    outline: none;
}

@media only screen and (max-width: 1150px){
    .response_container_middle{display:none}
    .backup_response_format_json{display:block;}
}

=======================================================================

JAVA代码部分:

由于代码无法从公司带出,所以只提供思路

1,springboot的整合请自行百度

2,关于测试应用接口的定时任务,本人采取的做法是100接口就有100个定时任务

3,随机生成数据问题

100个接口对应100个不同的实体类,那么怎么做呢?提供一个通用的方法,使用Random类随机生成各种类型的数据(能解决大部分的接口,特殊接口特殊对待)。

jdk有方法能够遍历每一个class里的属性,方法,属性的类型等,写一个方法去遍历传递进来的类,进行匹配,一般的参数都逃不过12种数据类型

byte,short,int,long,float,double,boolean,char,string,Integer,Date,Bigdecimal这12种。

4,关于每一个接口的参数字段有必传和非必传的问题

本人提供3种做法

1,在resources目录下生成json文件,里面存放json数据,每一个接口对应一个json文件,json文件里的key是类的属性,value是Y和N,Y代表必传,N代表非必传

每个定时任务读取对应的json文件,然后用随机的Random类生成boolean做为if条件

2,自定义注解,在每个类的属性上都定义这个注解,里面的值就是Y和N

3,使用StringTemplate模板

=================================================================================

 

posted @ 2018-08-05 20:45  me-ht  阅读(546)  评论(0编辑  收藏  举报