zoukankan      html  css  js  c++  java
  • RESTful api 功能测试

    0 为什么要写测试代码

        代码写好了,如果能点或者能看,开发人员一般会自己点点或看看,如果没有发现问题就提交测试;更进一步,代码写好后,运行测试代码,通过后提交测试。将流程抽象下:

    功能1编码->功能1测试->用户使用功能1

        我们假定功能1测试包括:代码测试+人工测试。如果功能1在用户使用之后不做修改,那么代码测试和人工测试都执行了1次;如果功能1迭代了10测,那么代码测试和人工测试都执行了10测,但编写测试代码只有1次。这是我认为需要写测试代码的原因,换言之,如果需求不迭代,原则上是可以不写测试代码的。

    1 什么是功能测试

        前面提到的测试为:代码测试和人工测试,想着机器能做的事情,人就不要做了。由于人对系统所有的操作,代码都是可以模拟,所以代码测试可以完成绝大多数人的测试。代码测试大致分为:

     

    图片来源

        在图片来源的链接地址中很好的介绍了它们分别是什么,从三角形的比例,可以看出功能测试的数量最少,由于功能测试是用户的视角测试测试软件是否满足需求。这里我简单理解下,功能测试基本等同于用户场景测试,如果理解有误欢迎指正。

        还需要说明一件事情,为什么不是写单元测试或者集成测试,而是写功能测试代码,其实单元测试和集成测试对于程序的健壮性绝对是大于功能测试的,而且如果有问题可以快速定位。但就项目情况,我选择功能测试,使用几个连续 Http 请求,完成一个功能点测试。

    2 hippie

        不得不说前端越来越有意思了,我说的主要是 npm 这个东西。hippie 介绍说是轻便的请求封装,用于 api 测试,具有功能强大和可视化特定。

    var api = require('hippie');
    
     
    
    describe('#test baidu', function () {
    
        describe('#首页', function () {
    
            it('get index return 200 ', function (done) {
    
                api()
    
                    .header("h1", "v1")
    
                    .get('https://www.baidu.com/')
    
                    .expectStatus(200)
    
                    .end(function (err, res, body) {
    
                        if (err) throw err;
    
                        done();
    
                    });
    
            });
    
        });
    
    });
    View Code

        示例向百度发了一个 Get 请求,带一个 header 头,有一个返回状态码 200 的假定,end()用于请求结束后对于预期或响应的处理。执行结果如下,

     

        Hippie 的优点就是简便、灵活,大致流程是:请求设置,param 参数对象经过 Serializers 方法处理,方式请求,响应内容经过 parsers 方法处理,验证假定,处理结果。Serializers 可以任意设置请求参数格式,parsers 可以将返回的内容转成对象方面后续处理。

    3 swagger-hippie

        由于 api 仿 REST 风格,所以使用 swagger 生成接口文档(由于我用的 .netcore,所以链接地址可能有点问题)

        swagger-hippie 是在 hippie 的基础上,验证发送的请求必须符合 /swagger/v1/swagger.json 文件的定义,也就是说测试是建立在文档的基础上,个人认为这一点对于团队合作是有益处的。

       

    5 功能测试应用

       

    var SwaggerParser = require('swagger-parser')
    var parser = new SwaggerParser()
    var path = require('path')
    var dereferencedSwagger
    var app = require('./server')
    
    var hippie = require('hippie-swagger')
    var baseUrl = 'http://192.168.1.139:6101'
    // var swagger = require('./my-dereferenced-swagger-file'); // see example for how to dereference swagger
    
    
    describe('#用户注册登录', function () {
        this.timeout(5000) // very large swagger files may take a few seconds to parse
    
    
        before(function (done) {
            // if using mocha, dereferencing can be performed prior during initialization via the delay flag:
            // https://mochajs.org/#delayed-root-suite
            parser.dereference(path.join(__dirname, './api.swagger.json'), function (err, api) {
                if (err) return done(err)
                dereferencedSwagger = api
                done()
            })
        })
    
        var mobile = '13812341234';
        var password = '123456';
        var code = '6666';
        describe('#注册', function () {
            it('1发送手机号验证码', function (done) {
                hippie(dereferencedSwagger)
                    .header("Accept", "text/plain; charset=utf-8")
                    .parser(function (body, fn) {
                        fn(null, body);
                    })
                    .base(baseUrl)
                    .url('/api/Mobile/{mobile}')
                    .method('GET')
                    .pathParams({
                        mobile: mobile
                    })
                    .expectStatus(200)
                    .expectBody("手机验证码已发送成功,请注意查收!")
                    .end(function (err, res, body) {
                        if (err) throw err;
                        done();
                    });
            });
            it('2校验手机验证码是否正确', function (done) {
                hippie(dereferencedSwagger)
                    .header("Accept", "text/plain; charset=utf-8")
                    .parser(function (body, fn) {
                        fn(null, body);
                    })
                    .base(baseUrl)
                    .url('/api/Mobile')
                    .method('POST')
                    .send({
                        mobile: mobile,
                        code: code
                    })
                    .expectStatus(200)
                    .expectBody("ok")
                    .end(function (err, res, body) {
                        if (err) throw err;
                        done();
                    });
            });
            it('3注册-设置密码', function (done) {
                hippie(dereferencedSwagger)
                    .header("Accept", "text/plain; charset=utf-8")
                    .parser(function (body, fn) {
                        fn(null, body);
                    })
                    .base(baseUrl)
                    .url('/api/AccountFt')
                    .method('POST')
                    .send({
                        mobile: mobile,
                        password: password
                    })
                    .expectStatus(200)
                    .expectBody("ok")
                    .end(function (err, res, body) {
                        if (err) throw err;
                        done();
                    });
            });
        });
    });
    View Code

    测试结果:

    上面完成了一个用户注册场景的3个api的调用测试。

    需要说明的有两点

    (1)hippie 支持服务器接口测试和 http 接口测试,这里的服务接口是指 js 实现 web 服务器。

    (2)对于接收是一个接口返回当做下一个接口参数的场景,可以在end()方法中设置。

  • 相关阅读:
    漫谈AOP开发之初探AOP及AspectJ的用法
    Spring AOP那些学术概念—通知、增强处理连接点(JoinPoint)切面(Aspect)
    深入理解Java虚拟机:OutOfMemory实战
    Java内存泄漏分析与解决方案
    漂亮回答面试官struts2的原理
    [小知识]不显示没有内容的UITableViewCell
    initWithCoder: 与initWithFrame:
    pageControl设置不居中显示,居左或居右
    Xcode中报错或警告信息整理,持续更新...
    [小技巧]阀值的使用
  • 原文地址:https://www.cnblogs.com/850391642c/p/9724940.html
Copyright © 2011-2022 走看看