接口测试是自动化测试过程中,投入产出比相对而言比较大的工作,我们组之前一直在用 Jmeter 执行接口测试工作,然后通过 Jenkins 调度执行 Jmeter,给出测试报告。
明确了存在的问题之后,又经过跟客户端同学开发的调研,发现他们希望我们在测试过接口之后,有这样一个页面,可以供他们使用。
显然这个时候我们展示的 HTML 静态页面,已经不能达到他们的需要了。
由于服务端开发接口开发完毕之后,提供了 Swagger UI 页面,但是他们可能由于某些原因,并没有设置header
,导致客户端开发基本不能调试,只能作为对接口的参数设置的大致了解,并没有起到相应的效果。
我们的思路就是借鉴服务端开发使用的 Swagger UI,定制化我们自己需求的既可以展示 Jmeter 执行结果,又能让开发在线调试的页面。
工欲善其事必先利其器,我先大致了解了一下 Swagger UI。
Swagger UI 是一个 API 在线文档生成和测试的框架。
(1)下载 Swagger UI
git clone https://github.com/swagger-api/swagger-ui.git
(2)创建一个空文件夹mkdir swagger
(3)初始化,并创建 package.json 文件npm init
(4)安装 express
npm install express --save
(5)在 swagger 中创建目录 public,并将刚才 clone 下来的 Swagger UI 中 dist 目录下的所有文件全部复制到 public 目录下面。
(6)创建并修改swagger.js
var express = require('express');
var http = require('http');
// 接口显示页面
app.use('/static', express.static('public'));
app.listen(8005, function () {
console.log('app listening on port 8005!');
});
(7)启动服务
cd swagger/
node swagger.js
打开http://127.0.0.1:8005/static/index.html
,可以看到在线的官方的 Demo 已经在本地搭建好了。
需要用到 Swagger Editor 生成一个合格的 Swagger UI 依赖的 Spec。
可以通过Swagger Editor,当然我推荐是自己本地部署一个 Swagger Editor,因为官方的这个链接,虽然我的网络是有代理的,但是在使用过程中会连接中断,使用体验并不好。
其实特别简单,git clone + npm intall
。
git clone https://github.com/swagger-api/swagger-editor.git
npm install
启动本地的 Swagger Editor,http://127.0.0.1:3001
,可以看到这样的页面。
当然这是官方的例子。
可以导出为 json 格式的文件(这是我们需要的最重要的产物)。
可以参考官方的文档,编写正确的符合格式的 Spec。OpenAPI-Specification
小贴士:因为我们部署的 Swagger UI 是 2.0 的版本,未使用 3.0 是因为,感觉 3.0 的源码我更看不懂。
将导出的 data.json 放置在swagger/public/data/
下,并且修改一下swagger/public/index.html
if (url && url.length > 1) {
url = decodeURIComponent(url[1]);
} else {
url = "/static/data/data.json";
}
重启node swagger.js
,然后重新打开浏览器,可以看到自己根据服务端 API 编写的 API 文档。
本地部署好 Swagger UI 之后,虽然生成的 curl 命令是正确的,但是点击try it out
,返回值一直是no content
,经过查阅确认是因为 JavaScript 存在的同源问题。那么怎么解决呢?
这里要感谢我同事的帮忙,帮忙一起解决了。
解决的思路:
在 swagger.js 中,封装了一个真正向服务端发请求的方法
/getResponse
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();
});
在 public/swagger-ui.js 中,修改
Operation.prototype.urlify = function (args, maskPasswords)
。将 url 值替换,实现对请求的拦截。
var url = '/getResponse';
这样,Swagger UI 直接点击 try it out 之后,请求是先发到 node
swagger.js,然后由 swagger.js 再向服务端真实发出请求,再将返回值,塞给 Swagger UI 解析展示。
当然过程中有 body 不能解析的情况,需要安装库
npm install multer --save
并加入代码
var bodyParser = require('body-parser');
var querystring = require('querystring');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
这个时候,在 Swagger UI 页面点击 try it out,已然可以真正的请求成功,也能让开发开始在线调试 API 了。
这里我其实走了取巧的方法,在生成的 Swagger Editor 中,如果配置如下,可以看到,Swagger Editor 中,我的配置是这样的
我将 tags 中加入了 Jmeter 执行的结果,在具体接口信息中,将 Summary 字段也变成了 Jmeter 执行的结果。
最后在 Swagger UI 界面可以查看这里的 json 文件展示的样式:
可以说,手动尝试部分已经全部走通了,需要做的是将 Jenkins 调度 Jmeter 执行生成的 jtl 传递给 Swagger UI。
分两步:
用 python 将 Jmeter 生成的 jtl,转化成我们需要的格式的 json,主要参照
{
"info": {
"version": "0.0.0",
"title": "测试服务端API"
},
"tags": [
{
"name": "测试一下",
"description": "【Jmeter build result】PASS"
}
],
"paths": {
"/aa.aa.aa.json": {
"get": {
"parameters": [
{
"description": "自已",
"default": "-1",
"required": "是",
"in": "query",
"type": "INT64",
"name": "fuid"
}
],
"produces": [
"application/json"
],
"tags": [
"测试一下"
],
"summary": "Jmeter result: true 2017-03-30 19:04:12",
"consumes": [
"application/x-www-form-urlencoded"
]
}
}
},
"host": "test.test.com",
"swagger": "2.0",
"schemes": [
"https"
]
}
在 swagger.js 中编写一个 upload API,可以将上一步生成的.json 文件传递过来。
安装 multer 库
npm install multer --save
upload API
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, __dirname + '/public/data/');
},
filename: function (req, file, cb) {
cb(null, file.originalname);
}
});
// 上传.json文件接口
app.post('/uploads', upload.single('file'), function(req, res, next){
var file = req.file;
res.send({'status': 'UPLOAD SUCCESS'});
});
这个时候,在 Jenkins 执行 Jmeter 接口测试之后,将 data.json 传递给,Swagger UI,然后 Swagger UI 显示结果,并供客户端开发在线调试。
客户端开发的需求基本都能得到满足,可以在线调试,可以看到正确的可执行的 curl 命令,可以看到关于这个接口当前的执行情况。
当然我对 Node 的认识非常非常皮毛,临时看了点介绍,之前一点没有了解。可能有些地方有更好的实现方式,可是我没有了解到。
当然还有很多需要优化的地方:
ToDo: