接口自动化 开源框架学习-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会自动运行脚本。

测试结果如下:

测试不通过

更新最后一个用例中的.expect(404).expect(403),测试通过。

测试通过

现在不管是测试代码的可读性还是测试报告的可读性,都比之前强多了。而且还可以使用--reporter参数让测试报告变成各种形状,比如

nyan

查漏补缺:总算是解决了代码可读性和测试报告的问题。再回过头来看看整个demo,突然发现调研了这么半天,竟然忽略了在很多业务场景中,调用API需要验证用户是否登录的问题。换句话说,需要在不同的http请求中保持cookie。

幸好supertest提供了这个解决方案,使用supertest的agent功能来解决这个问题。

    var request = require('superset')

    describe('测试cookie', function(){

      var agent = request.agent('待测server');
 
      it('should save cookies', function(done){
        agent
        .get('/')
        .expect('set-cookie', 'cookie=hey; Path=/', done);
      })
 
      it('should send cookies', function(done){
        agent
        .get('/return')
        .expect('hey', done);
      })
    })

可以看到第一个用例是测试cookie=hey,而到了第二个测试里面,由于被测实例由单纯的"request"变成了"request.agent()",所以cookie “hey”被agent带入到了第二个用例中,当访问"/return"的时候不用再重新set cookies了。

另外我们也可以通过在每次请求前去set cookie的方法达到同样的效果。

    .set('Cookie', 'a cookie string') 

最后如果是要测试授权资源的话,superagent也提供了.auth()方法去获取授权。

    request .get('http://local') 
        .auth('tobi', 'learnboost') .
    end(callback);

现在看上去调研工作算是差不多了,能够满足大部分的测试场景。接下来只需要再设计下测试代码结构,抽象下公共组件,做下参数化,分离下测试数据就搞定了。可是细想下,如果需要写了一大堆测试的话,难道要挨个去执行mocha xxx脚本的命令来跑测试?

还好项组目已经在用grunt构建工具。谷歌一下发现有一个grunt插件“grunt-mocha-test”貌似挺不错的。按照它的说明文档,只需要在grunt配置文件里面加上一段

grunt-mocha-test配置

其中reporter就是制定报告的格式, src就是需要执行的脚本的路径, *.js指定执行全部js格式的文件。

最后再注册一个grunt命令,比如:

    grunt.registerTask('apitest', 'mochaTest');

就能简单的在命令行中使用

    grunt apitest

来执行所有的测试文件了。这样也可以方便的在Jenkins中配置一个新的测试任务,加入持续集成。

至此,工具选型全部完成,核心是supertest,包装是mocha,执行用grunt,收工。

总结一下

总结一下,在工具选型的时候,建议考虑这些方面:

  • 结合项目技术栈使用
  • 新工具学习成本、维护成本、可扩展性
  • 是否可以简单实现代码满足所有业务场景,比如非REST风格的API,或者一些特殊场景
  • 代码易读,测试报告可视化
  • 脚本执行简单
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值