在项目上遇到一个需要对一个接口做200的编发测试,本来享用Postman来进行并发测试但是从网上看到这个工具好像并不具有编发测试的功能。考虑到Node.js天生的异步特性就想到了用Node.js写脚本来进行一个并发的测试。
这里考虑到了一个数据多个请求的并发(例如查询),以及每个请求都不同数据。不管是这两种情况的那种,我们的接口数据类型都是相对固定的,所以在下面的代码中的一个思路就是,每次请求体中的数据由一个固定函数生成,返回的数据就是这个请求用到的数据。组装的时候是将每次请求的个性化数据写入到请求参数模板中。
希望下面的内容对各位有用,有问题的话可以留言沟通。
var request = require('request');
//请求动态数据源
let DynamicDatas = [
{
"C0": "1",
"PK_RUZH": "1001X61*****00000G3I7",
"CARDNO": "5224272****77051",
"PSNNAME": "耿*巡",
"NATION": "汉族",
"BIRTHDAY": "20010627",
"SEX": "1",
"ADDR": "贵州省威宁彝族回*******金钟镇冒水村冒水组"
},
{
"C0": "1",
"PK_RUZH": "1001X61*****00000G3I7",
"CARDNO": "5224272****77051",
"PSNNAME": "耿*巡",
"NATION": "汉族",
"BIRTHDAY": "20010627",
"SEX": "1",
"ADDR": "贵州省威宁彝族回*******金钟镇冒水村冒水组"
}
];
//请求参数模型
let ParamsDataModel = {"PersonType":0,"pk_ruzh":"1001X61000000000G3I7","psnname":"耿*巡","sex":"男","nation":"汉族","birthday":"20010627","cardno":"522427200106277051","addr":"贵州省威宁彝族回族苗族自治县金钟镇冒水村冒水组","telephone":"18862283082","height":"145","weight":"122","politicaloutlook":"群众","nativeplace":"河北省","nature":"农村","nowaddr":"里河新村","marriage":"未婚","healthy":"健康","inway":"校园招聘","viewaddr":"台虹厂","computerlevel":"一般","englishlevel":"良好","salary":"2343","jtpsnname1":"柳任天","jtrelation1":"父母","jtunitname1":"宇航局","jtpostname1":"局长","jttelephone1":"13837999871","jjpsnname":"柳任天","jjdeptname":"父母","jjdutyname":"宇航局","jjrelationship":"13837999871","jystarttime1":"2021-02-04","jyendtime1":"2021-04-24","jyschoolname1":"常熟理工","jyxueli1":"本科","jymajor1":"计算机科学与技术","jystudyway1":"全日制","jystarttime2":"2021-02-04","isdisease":"无","issurgery":"无","isdecline":"无","isliver":"无","isallergy":"无","isspirit":"无","isquit":"无","iscrime":"无","iscompanyanpai":"有","agreement":true,"imageBase64":"data%3Aimage%2Fjpeg%3Bbase64%2C%2F9"};
//并发数,如果并发数为null,则根据数据量设置请求的并发数,CONCURRENCY_COUNT与DynamicDatas两个数据项有一个要为空
let CONCURRENCY_COUNT = null;
//请求路径
let REQUEST_URL = "http://*******.com:8000/******";
//请求方式
let REQUEST_TYPE = "POST";
let REQUEST_DATA_GEN = function(DynamicDatas,ParamsDataModel,Request_Time){
if(!(DynamicDatas instanceof Array))return ParamsDataModel;
let Index = Request_Time-1;
//数据个性化生成匹配区,将个性化数据源匹配给请求参数体
{
ParamsDataModel.pk_ruzh=DynamicDatas[Index].PK_RUZH;
ParamsDataModel.sex = DynamicDatas[Index].SEX==1?"男":"女";
ParamsDataModel.nation = DynamicDatas[Index].NATION;
ParamsDataModel.birthday= DynamicDatas[Index].BIRTHDAY;
ParamsDataModel.cardno= DynamicDatas[Index].CARDNO;
ParamsDataModel.addr= DynamicDatas[Index].ADDR;
}
return ParamsDataModel;
}//请求数据伪造函数,参数是初始化的数据,返回值是这次请求要用的数据
let REQUEST_METHOD = function () {
let req = function(Request_Time){
request({
url: REQUEST_URL,
method: REQUEST_TYPE,
json: true,
headers: {
"content-type": "text/plain",
"Accept-Encoding": "gzip, deflate, br",
},
//body: REQUEST_DATA_GEN(DynamicDatas,ParamsDataModel,Request_Time-1)
body: REQUEST_DATA_GEN(DynamicDatas,ParamsDataModel,Request_Time)
}, function(error, response, body) {
if (error==null && response.statusCode == 200) {
LogUtils("suc",Request_Time+"请求成功:",body)
}else{
LogUtils("err",Request_Time+"请求失败:",error);
}
});
}
let Request_Time = 1;
if(CONCURRENCY_COUNT==null)CONCURRENCY_COUNT=DynamicDatas.length;
while (true){
LogUtils("suc","开始第"+Request_Time+"次请求")
req(Request_Time);
Request_Time++;
if (Request_Time>CONCURRENCY_COUNT)break;
}
}
let LogUtils = function(type,mes,data){
switch (type) {
case "err" :console.log("Error--"+mes);break;
case "suc" :console.log("Success--"+mes);break;
case "war" :console.log("Warning--"+mes);break;
default:console.log("~~LogUtils()类型输入错误");
}
if(data!=undefined&&data!=null)console.log(data);
}
//开始执行请求测试
REQUEST_METHOD();