Skip to content

Latest commit

 

History

History
219 lines (149 loc) · 7.92 KB

Testing.md

File metadata and controls

219 lines (149 loc) · 7.92 KB

Testing

nwb uses Karma as a test runner, with Webpack to bundle test code and a Babel plugin to instrument it for code coverage reporting.

Default Testing Setup

Browsers

Karma runs tests in Chrome, which must be installed on the machine the tests are running on.

To configure this, provide karma.browsers config

Test Framework and Reporter

Mocha is configured as the default test framework - its BDD testing interface is available globally in tests.

To configure this, provide karma.frameworks config

A suitable reporter for Mocha is configured as the default if you don't configure the test framework, otherwise the Karma dots reporter is used.

To configure this, provide karma.reporters config

Assertion Library

expect v1 is made available by default for assertions and spies without having to install it in your own devDependencies - just import it when you need it:

import expect from 'expect'

Test Files

In the project skeletons created by nwb's new and init commands, the sample unit test is in a *.test.js file in the tests/ directory.

However, the default configuration supports having tests in any file which ends with one of the following suffixes, anywhere underneath a src/, test/ or tests/ directory:

  • .test.js
  • .spec.js

This supports having your tests in a separate top-level directory or co-located with the code they're testing, or both (e.g. co-located unit tests, separate integration tests).

To configure this, provide karma.testFiles config

Example Test

This is an example of a minimal unit test which will run with nwb test straight out of the box:

import expect from 'expect'

describe('Minimal unit test', () => {
  it('informs the reader', () => {
    expect('tautology').toEqual('tautology')
  })
})

Importing Code in Tests

Default test Webpack config is configured to alias src to the src/ directory, allowing you to write tests which use directory-independent import paths, no matter where you choose to put your test files.

Separate Test Directory

If you're using a separate test directory, the src alias allows you to organise your tests whichever way you want without having to adjust how you import the code to be tested, for example if you start out with a flat structure which you later want to organise using directories as the number of tests grows, by using the alias you won't have to change how you import the code being tested.

e.g., if the following directory structure exists in your project:

src/
  components/
    MyComponent.js

Then your tests can import this component like so:

import MyComponent from 'src/components/MyComponent'

Co-located Tests

If your tests are co-located with the modules they test, either as siblings or in __tests__ directories, tests will usually move too during any reorganisation, but you may find the src alias useful for shared test utilities:

e.g. if you set up the following directory structure:

src/
  __tests__/
    utils.js

Then all your co-located tests can import shared utilities like so, no matter where they are in the tree, and the utilities will be excluded from code coverage:

import utils from src/__tests__/utils

Using a Test Context Module

If you need to run some code before any of your tests run, the recommended approach is to create a context module for Webpack to load and use karma.testContext config to point to it.

You will need to use require.context() in this module to specify which test files to run, e.g.:

// tests.webpack.js
let context = require.context('./src', true, /\.spec\.js$/)
context.keys().forEach(context)
// nwb.js
module.exports = {
  karma: {
    testContext: 'tests.webpack.js'
  }
}

Note: if you provide karma.testContext and your tests would not have been picked up by the [default test files][#test-files] config, you will also need to provide a suitable karma.testFiles config so your tests can be excluded from code coverage.

Configuring Testing Libraries

Use a context module you need to configure testing libraries before running any tests. E.g. if you're using Enzyme to test some React code...

import Enzyme from 'enzyme'
import Adapter from 'enzyme-adapter-react-15'

Enzyme.configure({adapter: new Adapter()})

let context = require.context('./src', true, /\.spec\.js$/)
context.keys().forEach(context)

Global beforeEach/afterEach Hooks

A Webpack context module is also a suitable place for before/after hooks which should apply to all tests.

For example, if you want to make use of Expect's spies to fail tests by default if any unexpected error logging is performed, you could use a context module like this:

import expect from 'expect'

beforeEach(() => {
  expect.spyOn(console, 'error').andCall(msg => {
    let expected = false

    console.error.expected.forEach(about => {
      if (msg.indexOf(about) !== -1) {
        console.error.warned[about] = true
        expected = true
      }
    })

    if (expected) return

    console.error.threw = true
    throw new Error(msg)
  })

  console.error.expected = []
  console.error.warned = Object.create(null)
  console.error.threw = false
})

afterEach(() => {
  let {threw, expected, warned} = console.error
  console.error.restore()

  if (!threw) {
    expected.forEach(about => {
      expect(warned[about]).toExist(`Missing expected warning: ${about}`)
    })
  }
})

let context = require.context('./src', true, /-test\.js$/)
context.keys().forEach(context)

Code Coverage

Passing a --coverage flag when running tests will generate a code coverage report in coverage/.

Coverage will be measured automatically when your tests are run on Travis CI, or any other environment where a CONTINUOUS_INTEGRATION environment variable is set to true.

All project skeletons come with a .travis.yml which will post coverage results to codecov.io and coveralls after a successful build.

Excluding Code from Coverage

node_modules/, test files and test context modules are automatically excluded from code coverage.

Use karma.excludeFromCoverage config to specify additional paths which should be excluded from coverage reporting.

By default, this is configured to ignore code in a few common directory conventions for test code:

[
  'test/',
  'tests/',
  'src/**/__tests__/',
]