Test Driven Development with JavaScript

Author: Andrey Kucherenko

TDD steps

  • Navigation map

  • Test first

  • Assert first

  • Fail first

Test first

describe('Calculator', () => {

    it('should summarize two numbers', () => {
        

    });

});

Assert first

describe('Calculator', () => {

    it('should summarize two numbers', () => {
            sut.sum(1, 2).should.equal(3);
        }
    );

});

Fail first

> mocha --require babel-polyfill --compilers js:babel-register test/*.spec.js


  ․

  0 passing (4ms)
  1 failing

  1) String Calculator "before each" hook:
     ReferenceError: Calculator is not defined
      at Context.<anonymous> (/home/apk/workspace/lab/tdd/test/Calculator.spec.js:5:15)
      at callFn (/home/apk/workspace/lab/tdd/node_modules/mocha/lib/runnable.js:223:21)
      at Hook.Runnable.run (/home/apk/workspace/lab/tdd/node_modules/mocha/lib/runnable.js:216:7)
      at next (/home/apk/workspace/lab/tdd/node_modules/mocha/lib/runner.js:258:10)
      at Object._onImmediate (/home/apk/workspace/lab/tdd/node_modules/mocha/lib/runner.js:275:5)
      at processImmediate [as _immediateCallback] (timers.js:330:15)

Benefits

  • Unit tests coverage

  • Increases assurance of correctness

  • More complete explorations of requirements

  • Improved code

  • Code as documentation

  • Safe refactoring

  • No extra code

Pair programming

Pair Programming Rules

 
  • Ping Pong
  • Silent coding
  • Evil coder
  • Baby steps
  • ...
 

I don't use Pair Programming when:

 
  • Build nonproduction code
  • Work on spikes for future stories
  • Learn new tool or technique
  • Improve existing test coverage or fix code violations
 

Pair Programming Smells

 
  • Unequal access
  • Domination
  • Unhealthy relationship
  • Every player play his game
  • Endless debate
 

Emergent Design

Continious integration

Show me the source!

grunt-mutation-testing

coverage-blamer

Enzyme

chai.should();

beforeEach(() => {
    window.env = sinon.sandbox.create();
});

afterEach(() => {
    window.env.restore();
});

test_config.js

it('should show spy', () => {
    const callback = sinon.spy();
    
    PubSub.subscribe("message", callback);

    PubSub.publishSync("message");

    assertTrue(callback.called);
});
it('should show stub', () => {
    const message = 'an example message';
    const stub = sinon.stub().throws();
    const spy1 = sinon.spy();
    const spy2 = sinon.spy();

    PubSub.subscribe(message, stub);
    PubSub.subscribe(message, spy1);
    PubSub.subscribe(message, spy2);

    PubSub.publishSync(message, undefined);

    spy1.should.have.been.called;
    spy2.should.have.been.called;
    stub.should.have.been.calledBefore(spy1);
});
it('should show stub', () => {
    const myAPI = { method: () => {} };

    const spy = sinon.spy();
    const mock = sinon.mock(myAPI);
    
    mock.expects("method").once().throws();

    PubSub.subscribe("message", myAPI.method);
    PubSub.subscribe("message", spy);
    PubSub.publishSync("message", undefined);

    mock.verify();
    assert(spy.calledOnce);
});

https://github.com/kucherenko/tdd-javascript-template

Thank you

Test Driven Development with JavaScript

By Andrey Kucherenko

Test Driven Development with JavaScript

  • 1,845