最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Nodejs测试:从0到90(理论篇)

    正文概述 掘金(方凳雅集)   2020-12-08   299

    简介: 最近在负责一个基于nodejs的应用,在很多方面都经历了一个从无到有的过程,测试也是如此。刚开始时,代码都写不好,更别提测试了,那时测试为0。经历过一段时间后, 测试覆盖率在90%+。这就是我的从0到90。剩下的10,还有很长的路,且待下回分解。

    最近在负责一个基于nodejs的应用,在很多方面都经历了一个从无到有的过程,测试也是如此。刚开始时,代码都写不好,更别提测试了,那时测试为0。经历过一段时间后,尤其是看到 npm 上优秀的库的测试覆盖率都在100%时,痛下决心开始学习 nodejs 的测试, 目前这个应用的测试覆盖率在90%+。这就是我的从0到90。剩下的10,还有很长的路,且待下回分解。

    写在前面的

    对于开发者,测试的重要性毋庸置疑, 所谓”无测试不上线“,”无测试不重构“等。但在实践的过程中,测试总是有这样的那样的问题,随便列举下:

    • 不写测试。一般是觉得写测试浪费时间,也有可能是不会写;
    • 乱写测试。随意的写,没有规范,没有覆盖率,没有集成;
    • 写了跟没写一样。这样的测试通常是不可读、不可维护、不可信任,不可重复或独立运行(强依赖某些特定的环境或条件)、不执行(通常只是开发的时候执行一下,之后再也不会执行,或者执行太慢,没有人愿意执行)。

    一个好的测试

    一千个人眼中有至少二千种测试理念或方法,很难定义什么是一种好的测试。在团队一直负责测试的推进,我们的理念很简单,包括以下几个原则:

    • 覆盖75%+

    一个好的测试,最重要的衡量标准就是测了多少(覆盖率),75%是最低的标准。这个标准对java来说基本可行,但对nodejs不太适用,javascript是弱类型的、动态语言,没有编译阶段,很多错误只能在运行时才会被发现,所以需要更高的覆盖率,最好是100%,目前个人的标准是90%+。

    • 可重复执行

    每一个测试用例,无论在任何环境下,都应该可以反复执行,并产生相同的结果。只有这样,才能够相任你的测试,进而发现真正的bug。这也是集成测试最低要求。

    • 保持独立

    一个测试用例只测试代码的某一方面,如一个分支,且不强依赖某些特定的环境或条件。

    • 可读、可维护、可信任
    • 快快快

    无论是单个测试用例,还是集成测试,必须要保证测试执行足够的快。

    测什么

    测试测什么主要依据具体的需求、业务、成本、语言等,但也有一定的共性,单元测试准则 给出了一些准则可供参考,这里不再讨论。

    怎么测

    又是一个非常大的话题,本文仅从个人角度给出nodejs测试的工具及方法。

    概述

    框架

    Nodejs 测试框架众多,目前使用最广的是Mocha。本文详细说明下 Mocha, 并简要介绍几种其它框架。本文的示例,如无特别说明,都是基于Mocha.

    Mocha

    Nodejs测试:从0到90(理论篇)

    A simple, flexible, fun JavaScript test framework for node.js and the browser.

    Mocha 是一个功能丰富的Javascript测试框架,它能运行在Node.js和浏览器中,支持BDD、TDD式的测试。

    快速开始

    • 安装

      npm install -g mocha

    • 写一个简的测试用例

      var assert = require('chai').assert; describe('Array', function() { describe('#indexOf()', function () { it('should return -1 when the value is not present', function () { assert.equal(-1, [1,2,3].indexOf(5)); assert.equal(-1, [1,2,3].indexOf(0)); }); }); });

    • 运行

      $ mocha

    输出结果如下:

      .
    
       1 test complete (1ms)
    

    使用

    断言

    Mocha 允许你使用任何你想用的断言库,包括:

    • should.js BDD style shown throughout these docs
    • expect.js expect() style assertions
    • chai expect(), assert() and should style assertions
    • better-assert c-style self-documenting assert()
    • unexpected the extensible BDD assertion toolkit
    钩子 Hooks

    Mocha 提供了 before(), after(), beforeEach(), afterEach()等 hooks,用于设置前置条件及清理测试,示例如下:

    describe('hooks', function() {
      before(function() {
        // runs before all tests in this block
      })
      after(function(){
        // runs after all tests in this block
      })
      beforeEach(function(){
        // runs before each test in this block
      })
      afterEach(function(){
        // runs after each test in this block
      })
      // test cases
    })
    
    专用测试 或 跳过测试

    专用测试允许只测试指定的测试集或用例,只需在测试集或用例前加.only(),示例如下:

    describe('Array', function(){
      describe.only('#indexOf()', function(){
        ...
      })
    })
    

    跳过类似于 junit 的 @Ignore, 用于跳过或忽略指定的测试集或用例,只需在测试集或用例前加.skip(),示例如下:

    describe('Array', function(){
      describe.skip('#indexOf()', function(){
        ...
      })
    })
    
    编辑器插件

    除了使用 Mocha 提供的命令行外,还可以使用 编辑器插件 运行,目前支持了:

    • TextMate
    • JetBrains
    • Wallaby.js
    • Emacs

    以JetBrains为例,JetBrain 为其 IDE 套件(IntelliJ IDEA, WebStorm等)提供了 NodeJS, 可以直接运行或调试 mocha 测试用例。基本步骤:

    • 安装 NodeJS 插件(如果没有安装的话,默认IntelliJ IDEA, WebStorm都已安装):通过 Preferences > Plugins 查找名为 NodeJS 的插件并安装;
    • 添加 mocha 测试。通过 Edit Configuration 添加 Mocha, 示例如下:

    Nodejs测试:从0到90(理论篇)

    • 运行或调试。支持按目录、文件、测试集、测试用例等运行或调试,运行示例如下:

    Nodejs测试:从0到90(理论篇)

    其它

    以下列举几个基于 nodejs 的测试框架或工具,它们可用于 nodejs 或 浏览器端javascript 代码的测试,不在本文讨论范围,详见官方文档。

    Jasmine

    Nodejs测试:从0到90(理论篇)

    A Behavior Driven Development JavaScript testing framework

    更多见 官方文档.

    Karma Runner

    Nodejs测试:从0到90(理论篇)

    To bring a productive testing environment to developers

    更多见 官方文档.

    工具

    mocha 提供了测试的基本框架,在特定的场景下的测试还需要其它工具做以辅助,这个列举几个常用的工具。

    SuperTest

    SuperTest 提供对 HTTP 测试的高度抽象, 极大地简化了基于 HTTP 的测试。

    安装
    $  npm install supertest --save-dev
    
    使用示例
    • 简单的 HTTP 请求

      var request = require('supertest');

      describe('GET /user', function() { it('respond with json', function(done) { request(app) .get('/user') .set('Accept', 'application/json') .expect('Content-Type', /json/) .expect(200, done); }); });

    • 上传文件

      request(app) .post('/') .field('name', 'my awesome avatar') .attach('avatar', 'test/fixtures/homeboy.jpg') // ..

    • 修改响应头或体

      describe('GET /user', function() { it('user.name should be an case-insensitive match for "tobi"', function(done) { request(app) .get('/user') .set('Accept', 'application/json') .expect(function(res) { res.body.id = 'some fixed id'; res.body.name = res.body.name.toUpperCase(); }) .expect(200, { id: 'some fixed id', name: 'TOBI' }, done); }); });

    更多见 文档

    Istanbul

    代码覆盖(Code coverage)是软件测试中的一种度量,描述程式中源代码被测试的比例和程度,所得比例称为代码覆盖率。它有四个测量维度:

    • 行覆盖率(line coverage):是否每一行都执行了
    • 函数覆盖率(function coverage):是否每个函数都调用了
    • 分支覆盖率(branch coverage):是否每个if代码块都执行了
    • 语句覆盖率(statement coverage):是否每个语句都执行了

    Istanbul 是 JavaScript 语言最流行的代码覆盖率工具。

    快速开始
    • 安装

      $ npm install -g istanbul

    • 运行

    最简单的方式:

    $ cd /path/to/your/source/root
    $ istanbul cover test.js
    

    输出运行结果:

      ..
      test/app/util/result.test.js
         should static create
         should be success
         should be static success
         should be error
         should be static error
    
      299 passing (13s)
    
    [mochawesome] Report saved to /opt/source/node_modules/.mochawesome-reports/index.html
    
    =============================== Coverage summary ===============================
    Statements   : 92.9% ( 1505/1620 )
    Branches     : 85.42% ( 410/480 )
    Functions    : 94.33% ( 133/141 )
    Lines        : 93.01% ( 1504/1617 )
    ================================================================================
    Done
    

    这条命令同时还生成了一个 coverage 子目录,其中的 coverage.json 文件包含覆盖率的原始数据,coverage/lcov-report 是可以在浏览器打开的覆盖率报告,如下图所示:

    Nodejs测试:从0到90(理论篇)

    模式

    常见的测试模式包括TDD, BDD。

    TDD (Test Driven Development)

    测试驱动开发是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD的基本思路就是通过测试来推动整个开发的进行,但测试驱动开发并不只是单纯的测试工作,而是把需求分析,设计,质量控制量化的过程。整体流程如下:

    Nodejs测试:从0到90(理论篇)

    以一个阶乘的小程序为例。先写出的测试用例,如下所示。此时运行肯定会报错,因为被测试的程序还没有写。

    var assert = require('assert'),
        factorial = require('../index');
    
    suite('Test', function (){
        suite('#factorial()', function (){
            test('equals 1 for sets of zero length', function (){
                assert.equal(1, factorial(0));
            });
    
            test('equals 1 for sets of length one', function (){
                assert.equal(1, factorial(1));
            });
    
            test('equals 2 for sets of length two', function (){
                assert.equal(2, factorial(2));
            });
    
            test('equals 6 for sets of length three', function (){
                assert.equal(6, factorial(3));
            });
        });
    });
    

    开始写阶乘的逻辑,如下所示。

    module.exports = function (n) {
        if (n < 0) return NaN;
        if (n === 0) return 1;
    
        return n * factorial(n - 1);
    };
    

    此时再运行之前的测试用例,看其是否通过,如果全部通过则表示开发完成,如不通过则反复修改被测试的逻辑,直到全部的通过为止。

    BDD (Behavior Driven Development)

    行为驱动开发是一种敏捷软件开发的技术,它鼓励软件项目中的开发者、QA和非技术人员或商业参与者之间的协作。主要是从用户的需求出发,强调系统行为。其最显著的特征是,通过编写行为和规格说明来驱动软件开发。行为和规格说明看上去与测试十分相似,但它们之前还是有显著的不同。

    还是以上面的阶乘为例,BDD模式的测试用例如下:

    var assert = require('assert'),
        factorial = require('../index');
    
    describe('Test', function (){
        before(function(){
            // Stuff to do before the tests, like imports, what not
        });
    
        describe('#factorial()', function (){
            it('should return 1 when given 0', function (){
                factorial(0).should.equal(1);
            });
    
            it('should return 1 when given 1', function (){
                factorial(1).should.equal(1);
            });
    
            it('should return 2 when given 2', function (){
                factorial(2).should.equal(2);
            });
    
            it('should return 6 when given 3', function (){
                factorial(3).should.equal(6);
            });
        });
    
        after(function () {
            // Anything after the tests have finished
        });
    });
    

    从示例上看,BDD的测试用例与TDD最大的不同在于其措辞,BDD读起来更像是一个句子。因此BDD的测试用例可作为开发者、QA和非技术人员或商业参与者之间的协同工具,对开发者来说,如果你可以非常流畅地读测试用例,自然能够写出更好、更全面的测试。

    TDD vs BDD

    TDD和BDD本质和目标都是一致的。只是在实施方法上,进行了不同的探讨来完善整个敏捷开发的体系。TDD的迭代反复验证是敏捷开发的保障,但没有明确如何根据设计产生测试,并保障测试用例的质量,而BDD倡导大家都用简洁的自然语言描述系统行为的理念,恰好弥补了测试用例(即系统行为)的准确性。

    几乎所有基于Nodejs的库或应用都选择了BDD, 至于为什么,我还没有搞明白。

    断言

    目前比较流行的断言库包括:

    • should.js BDD style shown throughout these docs
    • expect.js expect() style assertions
    • chai expect(), assert() and should style assertions
    • better-assert c-style self-documenting assert()
    • unexpected the extensible BDD assertion toolkit

    这些断言库除了风格上略有不同外,实现在功能几乎完全一致,可根据个人喜好或应用需求选择。


    起源地下载网 » Nodejs测试:从0到90(理论篇)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元