接口测试 改造 Anyproxy 录制生成 postman 测试用例及 fuzz

syl7752 · December 09, 2016 · Last by syl7752 replied at December 16, 2016 · 2413 hits

目的

  • 录制接口,生成验证响应的postman测试脚本
  • 可在anyproxy界面删除不需要的请求,不想在文件中删
  • 根据请求进行fuzz,在界面可查看fuzz类型及响应状态

实现

导出

在index.html中增加导出选项

<a href="#"><span class="topBtn J_exportContainer"><i class="uk-icon-save"></i>Export</span></a>

增加导出界面exportPanel.js

var ExportPanel = React.createClass({
dealSave:function(){
var self = this,
userInput = React.findDOMNode(self.refs.pathInput).value;

self.props.onExportCollection && self.props.onExportCollection.call(null,userInput);
},
render:function(){
var self = this;

return (
<div>
<h4 className="subTitle">Export Postman collection</h4>
<div className="exportSection">
<div className="uk-form">
<input className="uk-form-large" ref="pathInput" defaultValue={self.props.defaultValue} type="text" width="300"/>
</div></div>
<div className="exportSection-btn">
<button type="button" className="uk-button" onClick={self.dealSave}>Save</button>
</div>
</div>
);
}
});

效果如图

在index.js中处理对保存按钮的处理

var exportBtn = $(".J_exportContainer");
exportBtn.on("click",function(e){
e.stopPropagation();
e.preventDefault();
$.getJSON("getRootPath",function(resObj){
var defaultPath = resObj.fullPath + "/default.postman_collection";
var ExportPanel = PopupContent["exportP"];
exportPanelEl = (<ExportPanel defaultValue = {defaultPath} onExportCollection={exportCollection} /> );
showPop({ left:"60%", content:exportPanelEl });
});


});

function exportCollection(userInput){
var data = {
type: 'export',
path: userInput,
data: showedIdSet
}
ws.send(data,function(){
hidePop();
});
}

这里是将录制的请求id都通过websocket发送给后端,后端去做导出请求的操作.我想让使用filter后只导出过滤后的请求,所以在filter.js中记录了录制的id,代码很少就不贴了
新建collection.js和request.js,用于保存集合和请求,websocketServer根据id查询db中的信息,返回request信息并添加到collection中

if (jsonData.type == "export") {
var coll = new collection();
async.forEach(jsonData.data, function(item, callback) {

getRequestFromDB(item, coll.get().id, function(err, req) {
coll.addRequests(req.get().id, req.getJson());
callback();
});
}, function(err) {
var filePath = jsonData.path;
fs.writeFileSync(filePath, JSON.stringify(coll.getJson()));
});
}

生成返回值的验证代码

case '[object number]':
st.push('//检查 ' + key + ', 类型是number, p = ' + p + ', key = ' + key + '\n');

//检查存在该字段
st.push('assertHasData(jsonData' + p + ',"' + key + '");\n');

//检查字段类型是否符合
st.push('tests["jsonData' + p + '.' + key + ' = "+ Object.prototype.toString.call(jsonData' + p + '["' + key + '"]).toLowerCase()] = Object.prototype.toString.call(jsonData' + p + '["' + key + '"]).toLowerCase() == "[object number]";\n');

//检查数值相等
st.push('tests["jsonData' + p + '.' + key + ' = ' + data[key] + '"] = jsonData' + p + '["' + key + '"] === ' + data[key] + ';\r\n');

break;

我只验证的类型和值,如果想自定义,可修改request里的parseToTestCode.至于postman脚本的格式,可在postman中导出查看文件格式
关于删除,是在表中新加了一列,代码可看源码,效果如图

生成的文件可导入postman使用或直接用newman执行

fuzz

修改了requestHandler.js,录制到请求后,根据请求执行fuzz的case,为不影响客户端,只返回原请求的response

var cases = fuzzer.generater.generate(options,userRule.shouldRunFuzzTest());

//get request body and route to local or remote
async.each(cases, function(item, callback) {
if (global.recorder) {
path = item.path;
resourceInfoId = global.recorder.appendRecord(resourceInfo);
resourceIdList.push(resourceInfoId);
item.resourceInfoId = resourceInfoId;
}

logUtil.printLog(color.green("\nreceived request to : " + host + path));
fetchReqData(function() {
routeReq(item, function() {
callback();
})
});
});

testCase的格式如下,我只加了11条case,如需要可在fuzzer.js中自定义

//no headers
var testCase1 = function(options) {
var testOptions = clone(options)
testOptions.description = "no headers";
testOptions.headers = {};
return testOptions;
}

添加支持参数"-F",为启动fuzz模式,详见bin.js

整体改造完成,效果如下:

使用

node lib/bin.js

源码

https://github.com/syl7752/anyproxy

共收到 2 条回复 时间 点赞

阅读源码中,向您学习

向阳 用 anyproxy 记录移动端 UI 测试数据 中提及了此贴 27 Sep 20:26
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up