zoukankan      html  css  js  c++  java
  • 前端单元测试总结及测试工具介绍

     1.为什么需要单元测试

    • 正确性:测试可以验证代码的正确性,在上线前做到心里有底
    • 自动化:当然手工也可以测试,通过console可以打印出内部信息,但是这是一次性的事情,下次测试还需要从头来过,效率不能得到保证。通过编写测试用例,可以做到一次编写,多次运行
    • 解释性:测试用例用于测试接口、模块的重要性,那么在测试用例中就会涉及如何使用这些API。其他开发人员如果要使用这些API,那阅读测试用例是一种很好地途径,有时比文档说明更清晰
    • 驱动开发,指导设计:代码被测试的前提是代码本身的可测试性,那么要保证代码的可测试性,就需要在开发中注意API的设计,TDD将测试前移就是起到这么一个作用
    • 保证重构:互联网行业产品迭代速度很快,迭代后必然存在代码重构的过程,那怎么才能保证重构后代码的质量呢?有测试用例做后盾,就可以大胆的进行重构

      2.前端相关的单元测试技术

      2.1 测试框架

      目前,前端的测试框架很多,像QUnit、jasmine、mocha、jest、intern等框架,这些框架各有特点,简单描述下,感兴趣的可以具体研究:

    • Qunit: 该框架诞生之初是为了jquery的单元测试,后来独立出来不再依赖于jquery本身,但是其身上还是脱离不开jquery的影子
    • jasmine: Behavior-Drive development(BDD)风格的测试框架,在业内较为流行,功能很全面,自带asssert、mock功能
    • mocha: node社区大神tj的作品,可以在node和browser端使用,具有很强的灵活性,可以选择自己喜欢的断言库,选择测试结果的report
    • intern: 看官方介绍该测试框架功能极其全面,似乎囊括了业内跟测试相关的所有功能

      2.2 断言库

    • chai:应该是目前组流行的断言库了,支持TDD(assert)、BDD(expect、should)两个风格的断言库
      var chai = require('chai'); 
      
      var assert = chai.assert; // typef assert === 'object'
      chai.should(); // 对Obejct.prototype进行拓展
    •  should.js: TJ的另外一个开源贡献
    • expect.js:BDD风格的另外一个断言库,基于should.js,是mini版的BDD库
    • assert(node自带核心模块): 可以在node中使用的断言模块

      2.3 mock库

      先来说说为什么需要mock吧:需要测试的单元依赖于外部的模块,而这些依赖的模块具有一些特点,例如不能控制、实现成本较高、操作危险等原因,不能直接使用依赖的模块,这样情况下就需要对其进行mock,也就是伪造依赖的模块。例如在使用XMLHttpRequest时,需要模拟http statusCode为404的情况,这种情况实际很难发生,必然要通过mock来实现测试。

    • sinon.js: 目前使用最多的mock库,将其分为spies、stub、fake XMLHttpRequest、Fake server、Fake time几种,根据不同的场景进行选择。

      2.4 test runner

    • karma: 设置测试需要的框架、环境、源文件、测试文件等,配置完后,就可以轻松地执行测试。

      3.单元测试技术的实现原理

    1. 测试框架:判断内部是否存在异常,存在则console出对应的text信息
    2. 断言库:当actual值与expect值不一样时,就抛出异常,供外部测试框架检测到,这就是为什么有些测试框架可以自由选择断言库的原因,只要可以抛出异常,外部测试框架就可以工作。
    3. mock函数:创建一个新的函数,用这个函数来取代原来的函数,同时在这个新函数上添加一些额外的属性,例如called、calledWithArguments等信息
      function describe (text, fn) {
          try {
              fn.apply(...);
          } catch(e) {
              assert(text)
          }
      }
       
      function fn () {
          while (...) {
              beforeEach();   
              it(text, function () {
                  assert();
              }); 
              afterEach();
          }
      }
       
      function it(text, fn) {
          ...
          fn(text)
          ...
      }
       
      function assert (expect, actual) {
          if (expect not equla actual ) {
              throw new Error(text);
          }
      }
      function fn () {
          ...
      }
       
      function spy(cb) {
          var proxy = function () {
              ...
          }
          proxy.called = false;
          proxy.returnValue = '...';
          ...
          return proxy;
      } 
       
      var proxy = spy(fn); // 得到一个mock函数 

      4.如何写单元测试用例

      4.1原则

    • 测试代码时,只考虑测试,不考虑内部实现
    • 数据尽量模拟现实,越靠近现实越好
    • 充分考虑数据的边界条件
    • 对重点、复杂、核心代码,重点测试
    • 利用AOP(beforeEach、afterEach),减少测试代码数量,避免无用功能
    • 测试、功能开发相结合,有利于设计和代码重构

      4.2 TDD

      一句话简单来说,就是先写测试,后写功能实现。TDD的目的是通过测试用例来指引实际的功能开发,让开发人员首先站在全局的视角来看待需求。具体定义可以查看维基;

      就个人而言,TDD不是一个技术,而是一种开发的指导思想。在目前互联网的开发环境下,业务开发很难做到TDD开发,一是因为需要更多时间编写单元测试用例;二是要求非常了解业务需求;三是要求开发人员有很强的代码设计能力。但是当我们写组件工具方法、类库的时候,TDD就可以得到很好地使用。

      4.3 BDD

      行为驱动开发要求更多人员参与到软件的开发中来,鼓励开发者、QA、相关业务人员相互协作。BDD是由商业价值来驱动,通过用户接口(例如GUI)理解应用程序。详见维基.

  • 相关阅读:
    高级特性(4)- 数据库编程
    UVA Jin Ge Jin Qu hao 12563
    UVA 116 Unidirectional TSP
    HDU 2224 The shortest path
    poj 2677 Tour
    【算法学习】双调欧几里得旅行商问题(动态规划)
    南洋理工大学 ACM 在线评测系统 矩形嵌套
    UVA The Tower of Babylon
    uva A Spy in the Metro(洛谷 P2583 地铁间谍)
    洛谷 P1095 守望者的逃离
  • 原文地址:https://www.cnblogs.com/gongcheng9990/p/4651992.html
Copyright © 2011-2022 走看看