Unit Testing in JS

5 things testing can do

  • Better Program design
  • Feature documentation (for developers)
  • Test understanding of the app
  • Quality Assurance
  • Continuous delivery

See https://medium.com/javascript-scene/what-every-unit-test-needs-f6cd34d9836d#.jg05xuy3o

5 things testing should do

  • Code under test must be deterministic
  • Be fast to execute

Source:  
http://jonnyreeves.co.uk/2012/stubbing-javascript-promises-with-sinonjs/

Language

Suite = A set of specs or tests

Spec = A single test

Assertion = A statement that performs a check on the software's output

Coverage = the amount of code within an app that has associated tests

Set up = code to run before a test

Tear down = code to run after a test

Test types

Unit = A function which tests another function's output

Spy = A function that records how many times it has been called and with what arguments

Stub = A spy with pre-programmed behaviour

Mock = A spy with expectations

Test types

Spies, stubs and mocks are all ways of handling non trivial code

 

Testing pure functions is easy

 

Testing events, timeouts, server calls and asynchronous code is not

Test types

When using a spy, the original function still runs,

When using a stub, it doesn’t

Test types

Stubs have all the functionality of spies, but instead of just spying on what a function does, a stub completely replaces it

Spies

Test spies are useful to test both callbacks and how certain functions are used throughout the system under test. The following simplified example shows how to use spies to test how a function handles a callback:

"test should call subscribers on publish": function () {
    var callback = sinon.spy();
    PubSub.subscribe("message", callback);

    PubSub.publishSync("message");

    assertTrue(callback.called);
}

Spies

When testing methods of your class you get extra information back about it under test, such as 

calledOnce

calledWith(message)

spy.getCall(0).args[0]

 

Use them like this

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

Stubs

Use a stub when you want to:

  1. Control a method’s behaviour from a test to force the code down a specific path. Examples include forcing a method to throw an error in order to test error handling.

  2. When you want to prevent a specific method from being called directly (possibly because it triggers undesired behaviour, such as a XMLHttpRequest or similar)

Test types

‘evergreen’ tests
Evergreen tests never fail, even when your code is broken. That is really bad.

Assertion types

 

Expect/should = Behaviour Driven Development

Assert = Test Driven Development

 

Assertion types

 

Expect/should - written closer to plain English

Assert - more concise

 

Assertion exmples

//TDD

assert.equal(2 - 1, 1);

//BDD

expect(2 - 1).to.equal(1);

Unit testing framework

  • Jasmine
  • Mocha
  • QUnit

 

Frameworks listed in order of popularity on GitHub

Assertion Libraries

  • Chai JS
  • Assert JS
  • jShould

 

Libraries listed in order of popularity on GitHub

Coverage

Coverage can be reported using a coverage framework such as:

  • Blanket
  • Istanbul

Automation

  • CLI with node
  • Webpack
  • Karma
  • Gulp
  • Grunt

Recommended stack

  • CLI with node
  • Mocha
  • Chai
  • Sinon
  • Istanbul

Recommended stack

  • CLI with node

For easy config and speed

 

e.g. "Test": "npm run mocha './path.to.my.specs'"

Recommended stack

  • Mocha

Powerful, simple API, stable and popular

 

Recommended stack

  • Chai

Write in plain English

 

Recommended stack

  • Sinon

The most popular
and plays nice with the other tools

 

Recommended stack

  • Istanbul

The most popular
but not without its issues

 

Testing in the client

Karma can run tests in real browsers

  • Configure Karma
  • Use preferred test framework
  • Create tests

Fixtures

HTML and JSON can be loaded into your suite.
HTML that is updated dynamically can be tested by running the JS in the beforeStart

Karma preprocessors

  • Coffee
  • TypeScript
  • Browserify

Karma plugins

In most cases, you don't need to explicitly specify plugins option. By default, Karma loads all sibling NPM modules which have a name starting with karma-*

& with Browserify

  • Use karma browserify plugin
  • Ensure it's run as preprocessor

& with Babel

In the object for the preprocessor add the transform property and relevant transform library

Before testing

  • Ensure your modules can run as tests
  • Object literals / revealing module works best

Cranking up a browser

Using the CLI

Switch to this branch

feature/webpack-coverage

 

yarn test

yarn coverage

The challenge

Write a suite of specs for the module

train-finder.js

Other tests

 

Integration tests

 

Functional tests

Making this work @ Zone

 

  • Start with crucial features
  • Set a target amount of coverage for each test suite
  • Teach your fellow developers how to test

    https://sean.is/writing/client-side-testing-with-mocha-and-karma/
Made with Slides.com