现如今,接口开发几乎成为一个互联网公司的标配了,无论是web还是app,哪怕是小程序,都离不开接口作为支撑,当然,这里的接口范围很广,从http到websocket,再到rpc,只要能实现数据通信的都可以称之为接口,面临着如此庞大的接口数据,如果更好的管理和测试他们都是一个比较头疼的问题,更主要的是很多业务场景是需要多个接口进行联调的,因此在接口开发完成后,一轮自动化测试能快速反馈出当前系统的状况,面对这样的需求,一个对测试人员友好的可视化接口自动化测试系统就显得必不可少了。那么,我们今天就来和大家聊聊如何实现一个小型的http接口自动化测试系统!
我们拿DOClever 做为这套系统的范本进行阐述,因为它是开源的,源码随时可以从GitHub和OSChina上获取,同时,这套系统内置了完整的自动化测试框架,从无需一行代码的UI测试用例编写,到更强大更灵活的代码模式,都提供了很友好的支持。
系统需求:
-
能在一个测试用例里可以对一个接口自由编辑其入参,运行并判断出参是否正确,同时可以查看该接口完整的输入输出数据
-
能在一个测试用例里可以对一组接口进行测试,自由调整他们的执行顺序,并根据上一接口的出参作为下一接口的入参条件。
-
能实现基本的逻辑判断,比如if,elseif,同时可以自定义变量用于存储临时值,并且定义当前用例的返回值。
-
提供一组辅助工具,可以快速实现数据打印,断言,用户输入,文件上传等操作。
-
能在一个测试用例里嵌入其他的测试用例,并自由对其测试用例传参,获取返回值来实现数据上的联动
-
当用户输入时,可以实现快速提示,自动完成,让用例的编辑更友好!
准备条件:
1.我们采用nodejs+mongodb的架构设计,node端采用express框架,当然你也可以根据你的喜好选择koa或者其他框架
2.前端我们采用vue+elementUI来实现展示,这样做无非是为了数据的快速响应和element提供丰富的UI支持来帮助我们快速搭建可视化页面。
架构设计:
先给出一张自动化测试的动态图:
那么,我们首先就从最基层的代理服务端来说起如果对接口数据进行转发。
所谓的接口数据转发无非就是用node做一层代理中转,好在node其实很擅长做这样的工作,我们把每一次的接口请求都看作是对代理服务端的一次post请求,接口的真实请求数据就直接作为post请求数据发给代理服务器,接口的host,path,method等数据都会包装在post请求的http header里面,然后我们用node的stream直接pipe到真实请求上去,在接受到真实的接口返回数据后,会把这个数据pipe到原先post请求的response上面去,这样就完成了一次代理转发。
有几点需要注意的是:
1.你在发送请求前需要判断当前的请求是http还是https,因为这涉及到两个不同的node库。
2.你在转发真实请求前,需要对post过来的http header进行一次过滤,过滤掉host,origin等信息,保留客户需要请求的自定义头部和cookies.
3.很多时候,接口返回的可能是一个跳转,那么我们就需要处理这个跳转,再次请求这个跳转地址并接受返回数据.
4.我们需要对接口返回过来的数据进行一个一次过滤,重点是cookie,我们需要处理set-cookie这个字段,去掉浏览器不可写的部分,这样才能保证我们调用登陆接口的时候,可以在本地写入正确的cookie,让浏览器记住当前的登陆状态!
5.我们用一个doclever-request自定义头部来记录一次接口请求的完整request和response过程!
下面是实现的核心代码,在此列举出来:
var onProxy = function (req, res) {
counter++;
var num = counter;
var bHttps=false;
if(req.headers["url-doclever"].toLowerCase().startsWith("https://"))
{
bHttps=true;
}
var opt,request;
if(bHttps)
{
opt= {
host: getHost(req),
path: req.headers["path-doclever"],
method: req.headers["method-doclever"],
headers: getHeader(req),
port:getPort(req),
rejectUnauthorized: false,
requestCert: true,
};
request=https.request;
}
else
{
opt= {
host: getHost(req),
path: req.headers["path-doclever"],
method: req.headers["method-doclever"],
headers: getHeader(req),
port:getPort(req)
};
request=http.request;
}
var req2 = request(opt, function (res2) {
if(res2.statusCode==302)
{
handleCookieIfNecessary(opt,res2.headers);
redirect(res,bHttps,opt,res2.headers.location)