unit test

2014.11.06

Phoebe

单元测试

       单元测试和质量保证(QA)是确保代码质量的两个重要方面,可维护代码是你所期待的。单元测试是开发者编写的一小段代码,用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为。例如,你可能会从字符串中删除匹配某种模式的字符,然后确认字符串确实不再包含这些字符了。

        单元测试是由程序员自己来完成,最终受益的也是程序员自己。可以这么说,程序员有责任编写功能代码,同时也就有责任为自己的代码编写单元测试。执行单元测试,就是为了证明这段代码的行为和我们期望的一致。

为什么要单元测试

  • 代码质量

  • 代码质量如何度量? 如果没有测试你如何保证你的代码质量?
  • 敏捷快速地适应需求

  • 单元测试是否也能让产品经理看得懂? 单元测试是否也能成为一个产品需求的Case?
  • 重构

  • 你有足够信心在没有单元测试的情况下发布你的重构代码吗? 如何检测你重构的代码符合需要?
  • 增强自信心

  • 全是绿灯! 单元测试全部跑通!

单元测试基本准则

1. 保持单元测试小巧, 快速

  理论上, 任何代码 Check-in 之前都应该把所有测试套件完整的跑一遍. 所以保持测试代码轻快能减少开发迭代周期.

2. 单元测试应该是全自动/非交互式的

  测试套件通常是定期执行的, 执行过程也必须是完全自动化才有意义. 输出结果需要人工检查的测试不是一个好的单元测试.

3. 立即修正失败的测试

  每个开发人员都应该保证新 Check-in 的测试用例能够跑成功, 并且当有代码 Check-in 现有测试用例也都能跑通过.

4. 保持测试的独立性

  为了保证测试稳定可靠且便于维护, 测试用例之间决不能有相互依赖, 也不能依赖执行的先后次序.

......

主要内容

  • sinon, sinon-chai
  • rewire
  • supertest
  • benchmark

When writing tests, it is extremely likely you are going to need to mock out the external dependencies of your system. In quite a lot of situations you can just use plain old Javascript Objects or simple functions as your mocks, however when it comes to mocking out more complex functionality, a mocking framework can really simplify things. One such mocking framework is Sinon JS.

sinon

sinon

用于 JavaScript 的测试监视(spy)、桩(stub)和仿制(mock)功能。不依赖其他类库,兼容任何单元测试框架。
  • spies 可用于测试回调函数,或者确认在测试中,系统中的某个方法/函数是如何被使用的 
  • stubs 在测试中控制一个方法的行为,以强制代码沿特定路径执行。例如测试错误处理时,可以强制一个方法抛出错误。
  • mocks 如果你想控制你的测试单元是用来说明他是否按你预期的执行,可以使用一个mock。

3 种创建 spies 的方法: sinon.spy()

  • var spy = sinon.spy();

    创建一个匿名函数用于记录其每次被调用的传入参数、this 值、异常和返回值。

  • var spy = sinon.spy(myFunc);

    监视一个已有的函数。

  • var spy = sinon.spy(object, "method");

    为 object.method 创建一个 spy,即使用 spy 替换原方法。这个 spy 的表现在各方面都和原方法很像。原方法可以通过调用 object.method.restore() 方法还原。返回的 spy 就是替换原方法的函数对象,即 spy === object.method 。

创建 Stub 的方法

  • var stub = sinon.stub();

    创建一个匿名的 stub 函数。

  • var stub = sinon.stub(object, "method");

    使用一个 stub 函数替代 object.method。原函数可以通过调用 object.method.restore() (或 stub.restore())方法来还原。如果 object.method 不是一个函数,则会抛出一个异常来帮助你避免类型错误。

  • var stub = sinon.stub(object, "method", func);

    使用 func 来替换 object.method,并且被包装在一个 spy 中。object.method.restore() 可以恢复原方法。

  • var stub = sinon.stub(obj);

    stub 该对象的所有方法。

Sinon–Chai provides a set of custom assertions for using the Sinon.JS spy, stub, and mocking framework with the Chai assertion library. You get all the benefits of Chai with all the powerful tools of Sinon.JS.

rewire

Rewire is a dependency injector which has been designed to modify the behaviour of a module such that you can easily inject mocks and manipulate private variables. This might sound like quite a powerful and potentially dangerous tool, and it is, however it can be very

useful when you have

code that looks

something like this:

var fs = require('fs')

module.exports = function doesFileExist(callback) {

    fs.exists('/tmp/myfile', function (error, exists) {
        if (exists) {
            callback(error, true)
        } else {
            callback(error, false)
        }
    }) 
}

supertest(Nock)

Need to test a HTTP server? Supertest is your friend! It makes testing HTTP servers and Express applications super easy.

TIP: Instead of passing in a URL to the request object, pass in your Express instance to easily test your endpoints without having to have your application running separately.

A robust benchmarking library that works on nearly all JavaScript platforms, supports high-resolution timers, and returns statistically significant results.

unit test

By Phoebe Li

unit test

  • 205