Test Driven Development with JavaScript

测试驱动开发(TDD)

什么是TDD

  • TDD 是敏捷开发中的一项核心实践和技术,及方法论

  • TDD的原理是在开发功能代码之前,先编写单元测试用例代码

  • TDD 是 XP(Extreme Programming)的核心实践

Kent Beck

1999. Extreme Programming Explained: Embrace Change

WHY?

为什么TDD

传统编码

TDD编码

 

需求分析,想不清楚细节,管他呢,先开始写

需求细节不明确,跟PM确认

确认几次终于写完所有逻辑

运行起来测试一下,靠,果然不工作,调试

调试好久终于工作了

转测试,QA 测出 bug,debug, 打补丁

终于,代码可以工作了

一看代码烂的像坨屎,不敢动,动了还得手工测试

传统编码

 

先分解任务,分离关注点, Tasking

列 Example,用实例化需求,澄清需求细节

写测试,只关注需求,程序的输入输出,不关心中间过程

写实现,不考虑别的需求,用最简单的方式满足当前需求即可

重构,用手法消除代码里的坏味道, Bad Smell

写完,手动测试一下,基本没什么问题,有问题补个用例,修复

转测试,小问题,补用例,修复

代码整洁且用例齐全,信心满满地提交

传统编码

TDD编码

如何TDD

测试失败

➜  banma_fe_starfire git:(feature/PSFECD-97) ✗ npm run test:unit

> banma_page@1.0.0 test:unit /Users/songyang/code/banma/banma_fe_starfire
> mocha --require babel-core/register ./static/**/*.spec.js



  #dateUtils
    #toDuration
      ✓ should return formatted date string from seconds
    #toRelativeDate
      1) should display relative date without time
      ✓ should display relative date with time


  2 passing (31ms)
  1 failing

  1) #dateUtils
       #toRelativeDate
         should display relative date without time:

      AssertionError: expected '09:09' to equal '09:090'
      + expected - actual

      -09:09
      +09:090

测试成功

➜  banma_fe_starfire git:(feature/PSFECD-97) ✗ npm run test:unit

> banma_page@1.0.0 test:unit /Users/songyang/code/banma/banma_fe_starfire
> mocha --require babel-core/register ./static/**/*.spec.js



  #dateUtils
    #toDuration
      ✓ should return formatted date string from seconds
    #toRelativeDate
      ✓ should display relative date without time
      ✓ should display relative date with time


  3 passing (20ms)

工具与框架

describe('#dateUtils', () => {
  describe('#toDuration', () => {
    it('should return formatted date string from seconds', () => {
      toDuration(59).should.equal('59秒')
      toDuration(60).should.equal('1分0秒')
      toDuration(3600).should.equal('1时0分0秒')
      toDuration(7261).should.equal('2时1分1秒')
    })
  })

  describe('#toRelativeDate', () => {
    let clock
    beforeEach(() => {
      clock = sinon.useFakeTimers(now.getTime())
    })

    afterEach(() => {
      clock.restore()
    })

    it('should display relative date without time', () => {
      toRelativeDate(lastYear.getTime() / 1000).should.equal('2017-05-16')
      // ...
    })

    it('should display relative date with time', () => {
      toRelativeDate(yesterday.getTime() / 1000, withTime).should.equal('昨天 09:09')
      // ...
    })
  })
})

BDD测试风格

$ mkdir workshop
$ cd workshop
$ npm init
$ npm i -S mocha
$ mkdir test
$ touch test/test.js
{
  "name": "workshop",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "mocha"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "mocha": "^5.2.0"
  }
}

安装指南

1

2

3

const assert = require('assert')

describe('my test cases', () => {
  it('it should be true', () => {
    assert.equal(1 === 1, true, '1 === 1 should be true')
  })
})

第一行测试代码

实战DEMO

FizzBuzz

写一个fizzBuzz函数,要求在返回一个长度为100,值从1到100的数组

v0

FizzBuzz

写一个fizzBuzz函数,要求在返回一个长度为100,值从1到100的数组

v1

当值能被3整除时返回Fizz
当值能被5整除时返回Buzz

FizzBuzz

写一个fizzBuzz函数,要求在返回一个长度为100,值从1到100的数组

v2

当值能被3整除时返回Fizz
当值能被5整除时返回Buzz
当值能同时被3与5整除时返回FizzBuzz

Thanks

Test Driven Development for Javascript

By Owen Yang

Test Driven Development for Javascript

OdessaJS 2015

  • 841