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

Made with Slides.com