测试来带个节奏之 API 测试工具篇
作者:大大灰灰狼 发布时间:[ 2016/8/23 10:47:33 ] 推荐标签:软件测试 API测试工具
目组里面的e2e测试运行多年,历经了经常会出现各种莫名其妙的环境问题、运行变慢等问题后,项目组终于决定引入API功能测试。同时可以在尽量保证测试覆盖率的前提下把重复测试的e2e测试脚本清理掉,提高持续集成效率(策略参考测试金字塔)。
那么问题来了,做API功能测试如何选择工具勒?API功能测试可以通过soapUI或者postman等带GUI的工具简单录制脚本执行,也可以通过开源项目工具自己写代码完成。根据项目的实际情况,这里我们选择使用后者,便于定制和持续集成。
工具选择
目前市面上比较流行的API测试开源框架有很多。首先能够想到的是REST-assured。Rest-Assured 是一套由 Java 实现的 REST API 测试框架,它是一个轻量级的 REST API 客户端,可以直接编写代码向服务器端发起 HTTP 请求,并验证返回结果。官方的介绍是:
Testing and validation of REST services in Java is harder than in dynamic languages such as Ruby and Groovy. REST Assured brings the simplicity of using these languages into the Java domain.
打开github提交记录,发现这个框架近还有人在持续提交代码,说明维护的还不错,列为备选项目。
另外经过各种途径了解到目前还有一套非常流行的,由大神tj等人开发的nodeJS测试框架supertest。这是一套脱胎于的superagent的API测试框架,官方的说法是:
Super-agent driven library for testing node.js HTTP servers using a fluent API
HTTP assertions made easy via superagent.
稍微对比一下这两个工具,从几个方面来考虑取舍:
1、项目代码基于Java,同时也有NodeJS代码在里面,从环境上来讲两个工具都不需要再额外配置。这点两者打个平手。
2、学习成本方面,两个工具都可以方便的从网上搜出一大堆学习资料,而且官方给的资料也比较全。又是平手。
3、维护成本上讲,supertest是基于动态语言,不需要浪费编译时间;万一写错了代码立马改完立马重新跑起来。而且官网上号称"SuperTest works with any test framework"可扩展性貌似也比较强。
4、从可移植性上看,supertest由于使用nodeJS,理论上如果框架做的够好,只要有node,可以把同一套脚本丢到各种不同的地方运行。
5、后再对比下易用性。安装方面,REST-assured通常会借助如maven、grade之类的工具安装,配置运行环境比较麻烦。而superset只需要简单的一行npm install 命令安装后即可使用。考虑到我比较懒,supertest完胜,酱。
开始入坑
开始学习supertest。
首先打开它的github,了解supertest几个关键信息:
· 继承了superagent所有的API和用法。
· 使用前需安装node,然后用npm install supertest --save-dev或者cnpm install supertest --save-dev安装supertest。
· 和superagent一样,需要通过调用.end() 执行一个request请求。
· 调用.expect()来做断言,如果在里面填入数字,默认是检查http请求返回的状态码;
完了我们来分析下官方示例代码,然后仿造它来撸一段代码试试看。
var request = require('supertest');
var express = require('express');
var app = express();
这里的app目测只是用来做一个mock server,跟supertest有关的测试只有下面这部分
request(app)
.get('/user')
.expect('Content-Type', /json/)
.expect('Content-Length', '15')
.expect(200)
.end(function(err, res) {
if (err) throw err;
});
分析这段测试代码,首先是用request(app)实例化一个server,然后是.expect()分别验证了response header里面的content-type,content-length和response的http status是否200. 这是supertest的基本写法了。
小试牛刀
我们用全球大的同性交友平台github来做个实验,设计一个判断是否成功进入首页的用例。
准备工作:使用你的chrome,打开develop tools的Network标签,先看看进入github首页时上有哪些请求,记录下进入首页的请求,找到这个请求的URL,Method等关键信息。
实施阶段:我们再随便打开个vim,记事本什么的文本编辑工具撸一小段代码试试刀:
var request = require('supertest')('https://github.com/');
request
.get('/')
.expect(2010)
.end(function(err, res) {
if (err) throw err;
});
保存下来,命名个test.js什么的,然后运行它
node test.js
然后你发现得到这个提示异常的结果
这说明我们的断言成功了!把.expect(2010)改成实际会返回的.expect(200)再试试看,没有返回异常结果说明测试通过了!
优化一下:虽然测试成功了,但是这个测试结果的可读性实在是有些令人不甚满意,尤其是测试成功了连个提示都没有。
于是我们考虑用官网例子中提到的测试框架Mocha来优化下这个测试。
Mocha是一个的JavaScript测试框架,长得跟Jasmine一个样。官网上的介绍是:
Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases. Hosted on GitHub.
这个框架提供了各种style的测试报告。结合supertest使用,可以让我们的API测试报告可视化上一个档次。
顺便可以加上个常用的post请求的测试:
var request = require('supertest')('https://github.com');
describe('Github home page',function(){
this.timeout(10000);
before('must be on home page',function(done){
request.get('/')
.expect(200,done);
});
it('could be navigated to register page',function(done){
request.get('/join')
.expect(200,done);
});
it('will refuse the request if username has been taken',function(done){
request.post('/signup_check/username')
.type('form')
.send('value=lala')
.expect(404)
.end(function(err,res){
if (err) return done(err)
done();
})
});
});
这个测试比起刚才的版本更加具有可读性,借助Mocha框架,每段测试之前都有一个描述信息,一看知道你这段代码在测试什么。
其中before()是Mocha提供的hook,相当于beforeAll,会在所有测试前执行。其他hook还有会在所有测试执行之后执行的after(),会在每个测试前都执行一遍的beforeEach()和会在每一个测试执行之后都执行一遍的afterEach()。hook用在清理测试数据方面会非常方便。
然后describe()描述了是测试的是什么东西:
describe('描述测试对象',function(){
//测试用例
})
而`describe()`里面的`it()`则描述了具体的测试用例:
it('描述测试用例', function(done){
//测试用例实现
done();
})
done()是Mocha提供的回调方法,如果没有done()的话Javascript回一直等待回调致超时。顺带提一下Mocha的默认超时时间是2秒,所以在describe的下面加上this.timeout(10000);把超时时间重新设置为10秒。
需要注意的是在虽然使用Mocha的时候可以忽略superset的.end(),而直接在.expect()添加done参数,例如.expect(200,done)。但是如果使用了.end()的写法的话,仍然需要在.end()块儿中调用done()。
后个用例中的.send('value=lala')是post的request body,通过.type()来指定类型。.type()在缺省状态下默认是JSON(详见superagent源代码),本例中使用的是form类型。 当然,也可以不用send()而是选择直接在post的url中加上参数request.post('/signup_check/username?value=lala'),但是如果要参数化的话,还是推荐用.send()。
Mocha还提供了watch功能,使用带参数的命令mocha -w 测试脚本.js来监视测试脚本,当脚本有变化的时候Mocha会自动运行脚本。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11