前言

接口测试是自动化测试过程中,投入产出比相对而言比较大的工作,我们组之前一直在用 Jmeter 执行接口测试工作,然后通过 Jenkins 调度执行 Jmeter,给出测试报告。

测试报告如下:

痛点

明确了存在的问题之后,又经过跟客户端同学开发的调研,发现他们希望我们在测试过接口之后,有这样一个页面,可以供他们使用。

需求:

显然这个时候我们展示的 HTML 静态页面,已经不能达到他们的需要了。

由于服务端开发接口开发完毕之后,提供了 Swagger UI 页面,但是他们可能由于某些原因,并没有设置header,导致客户端开发基本不能调试,只能作为对接口的参数设置的大致了解,并没有起到相应的效果。

我们的思路就是借鉴服务端开发使用的 Swagger UI,定制化我们自己需求的既可以展示 Jmeter 执行结果,又能让开发在线调试的页面。

Swagger UI

工欲善其事必先利其器,我先大致了解了一下 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 已经在本地搭建好了。

改造之旅

第一步,希望替换官方的 API

需要用到 Swagger Editor 生成一个合格的 Swagger UI 依赖的 Spec。

可以通过Swagger Editor,当然我推荐是自己本地部署一个 Swagger Editor,因为官方的这个链接,虽然我的网络是有代理的,但是在使用过程中会连接中断,使用体验并不好。

插播一句 Swagger Editor 的本地部署

其实特别简单,git clone + npm intall

本地安装 Swagger Editor

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 的源码我更看不懂。

配置 json 文件

将导出的 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 了。

Jmeter 执行结果显示

这里我其实走了取巧的方法,在生成的 Swagger Editor 中,如果配置如下,可以看到,Swagger Editor 中,我的配置是这样的

我将 tags 中加入了 Jmeter 执行的结果,在具体接口信息中,将 Summary 字段也变成了 Jmeter 执行的结果。

最后在 Swagger UI 界面可以查看这里的 json 文件展示的样式:

可以说,手动尝试部分已经全部走通了,需要做的是将 Jenkins 调度 Jmeter 执行生成的 jtl 传递给 Swagger UI。

将 Jmeter 执行结果传递过来

分两步:

安装 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:

参考文档

Swagger UI 教程 API 文档神器 搭配 Node 使用 web api 接口文档 mvc 接口文档

基于 swagger 的 RESTful API 开发实践


↙↙↙阅读原文可查看相关链接,并与作者交流