背景:jmeter 生成 api 报告后,为了方便开发人员跟踪调试错误接口,故搭建 jtl 部署到 swagger 平台。
作用:开发人员可以根据转换后的 swagger,一键执行错误接口,进行重新问题。
1.在生成 jtl 文件前,我们需要对 jmeter 系统文件 user.properties 进行设置。
jmeter.save.saveservice.output_format=xml
jmeter.save.saveservice.response_data=true
jmeter.save.saveservice.samplerData=true
jmeter.save.saveservice.requestHeaders=true
jmeter.save.saveservice.url=true
jmeter.save.saveservice.responseHeaders=true
jmeter.save.saveservice.thread_name=true
jmeter.save.saveservice.response_data.on_error=true
2.jtl 文件转换 swagger.json 脚本
import xml.etree.ElementTree as ET
tree = ET.parse(r'C:\Users\Administrator\Desktop\test.xml')
root = tree.getroot()
data = {}
swagger_json = {}
swagger_json.setdefault("swagger", "2.0")
swagger_json.setdefault("info", {"version": "1.0", "title": "可视化api服务端测试"})
swagger_json.setdefault("tags", [{"name": "visual-controller-fail", "description": "【Jmeter Test Result】 FAILED"},{"name": "visual-controller-pass", "description": "【Jmeter Test Result】 PASS"}])
swagger_json.setdefault("schemes", ["http"])
paths = {}
definitions = {}
httpSamples = root.findall("httpSample")
for i in range(httpSamples.__len__()):
httpSample = httpSamples[i]
hattribute = httpSample.attrib
summary = hattribute.get("lb")
status = hattribute.get("s")
rc = hattribute.get("rc")
if "JDBC" in summary:
continue
print(httpSample.findall("method"))
method = httpSample.findall("method")[0].text
rcode = hattribute.get("rc")
header = httpSample.findall("requestHeader")[0].text
queryString = httpSample.findall("queryString")[0].text
headers = {}
for h in header.split("\n"):
if h != '':
headers.setdefault(h.split(": ")[0], h.split(": ")[1])
url = str(httpSample.findall("java.net.URL")[0].text).split(headers.get("Host"))[1]
model = url.split("/")[-1]
definition_name = model[0].upper()+model[1:]
swagger_json.setdefault("host", headers.get("Host"))
parameters = []
token = headers.get("Authorization")
if queryString is not None:
try:
body = json.loads(queryString)
switch = {
str:"string",
int:"integer($int32)",
float:"double",
dict:"map",
list:"list",
tuple:"array",
bool:"boolean"
}
parameters.append({"in":"header","name":"Authorization","default":token,"required":True,"type":"string"})
parameters.append({"in":"body","name":model,"description":model,"required":True,"schema":{"$ref":'#/definitions/'+definition_name}})
properties = {}
for key, value in body.items():
try:
tp = switch[type(value)]
except KeyError as e:
tp = "object"
properties.setdefault(key,{"type":tp,"example":value})
definitions.setdefault(definition_name,{"type": "object", "properties": properties, "title": definition_name})
except Exception as e:
res = "{\""+ str(queryString).replace("=","\":\"").replace("&","\",\"")+"\"}"
body = json.loads(res)
for key, value in body.items():
if value != '':
parameters.append(
{"in": "query", "name": key, "default": value, "required": True, "type": "string"})
else:
parameters.append(
{"in": "query", "name": key, "default": value, "required": False, "type": "string"})
else:
parameters.append(
{"in": "header", "name": "Authorization", "default": token, "required": True, "type": "string"})
body = {}
if status == "true":
paths.setdefault(url, {
str(method).lower(): {"responses": {rc: {"description": "OK"}}, "tags": ["visual-controller-pass"],
"summary": summary, "description": "",
"consumes": ["application/json","application/x-www-form-urlencoded; charset=UTF-8"],
"produces": ["application/json"],
"parameters": parameters}})
if status == "false":
response_data = httpSample.findall("responseData")[0].text
paths.setdefault(url, {
str(method).lower(): {"responses": {rc: {"description": response_data}}, "tags": ["visual-controller-fail"],
"summary": summary, "description": "",
"consumes": ["application/json",
"application/x-www-form-urlencoded; charset=UTF-8"],
"produces": ["application/json"],
"parameters": parameters}})
swagger_json.setdefault("definitions",definitions)
swagger_json.setdefault("paths",paths)
print(swagger_json)
data = json.dumps(swagger_json)
with open("jmeter.json","w",encoding="utf8") as file:
file.writelines(data)
3.搭建本地 swagger-ui 环境,添加导入 json 文件模块。
3.1.进入官网下载 ui 项目,项目在 github 中的位置:GitHub:Swagger-ui,若 github 也无法访问详见最后文件下载地址。
3.2.下载到本地进行解压,首先看目录结构你可能会懵逼,不要紧,主体部分都放入 dist 目录下,可以进入 dist 目录打开 index.html 看下界面,可以发现基本的模式还是有了,只不过是静态的文件,接下来进行 nodejs 配置,使其可以进行端口访问,直接使用 node 命令访问 index.js 没有反应,英语稍微好点点的同学可以看下官网的配置步骤,接下来手动配置 ui 环境。
3.3.下面进行项目的配置,新建 node_app 文件夹,初始化 node,输入好信息后会自动创建 package.json 文件,如下图:
初始化命令 npm init,出现如下信息,填的地方可以随便写,也可以不写
3.4.将下载的 swagger-ui 中的 dist 文件夹拷贝到 node_app 下:
3.5.安装 express,如果出错可以去 nodejs 安装目录进行安装
>>npm install express
3.6.创建 swagger.js,并将如下代码写入该 js 中
var express = require('express');
var http = require('http');
var app = express();
var fs = require('fs');
var multer = require('multer');
app.set('view engine','ejs');
var createFolder = function(folder){
try{
fs.accessSync(folder);
}catch(e){
fs.mkdirSync(folder);
}
};
var uploadFolder = './public/data/';
createFolder(uploadFolder);
var storage = multer.diskStorage({
destination:function(req,file,cb){
cb(null,uploadFolder);
},
filename:function(req,file,cb){
cb(null,file.originalname);
}
});
var upload = multer({storage:storage})
// 接口显示页面
app.use('/static', express.static('public'));
app.listen(8005, function () {
console.log('app listening on port 8005!');
});
//文件上传
var filename = '';
app.post('/static/index', upload.single('file'), function(req, res, next){
filename = req.file.originalname;
res.render('index',{filename:filename});
});
app.get('/static/form', function(req, res, next){
var index = fs.readFileSync('./public/form.html', {encoding: 'utf8'});
res.send(index);
});
app.use('/getResponse', function(req, response){
var headers = {
'aa': req.headers.aa,
'xx':req.headers.xx,
'content-type': req.headers["content-type"]
};
if(req.query){
path = req.path.replace('/getResponse', '') + "?" + querystring.stringify(req.query)
}else{
path = req.path.replace('/getResponse', '')
}
var options = {
hostname: config_data.host,
path: path,
headers: headers,
method: req.method
};
var req = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
response.send(chunk);
console.log('返回值: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.write(querystring.stringify(req.body));
req.end();
});
app.listen(3000);
3.7 启动 swagger-ui
>>node swagger.js
4.我们打开浏览器进行访问:
http://ip:8005/static/form
5.生成 swagger.json 后上传到 swagger 系统,如下图: