Skip to content

Writing Tests

Darcy Clarke edited this page Feb 26, 2020 · 5 revisions

All tests are written using tap as our test framework.

Tests go in test/tap/name-of-test.js, you can see boiler plate for this below.

All tests can be run directly with node test/tap/name-of-test.js or exactly as the larger npm test suite does with npm run tap test/tap/name-of-test.js.

Some existing tests may require that you run test/tap/00-config-setup.js once before they will work. New tests should not require this.

If you don't need to do any setup or cleanup you can skip those steps.

'use strict'
var test = require('tap').test
var common = require('../common-npm.js')

function setup () {
  cleanup()
  …sync setup…
}

function cleanup () {
  …sync cleanup…
}

test('setup', function (t) {
  setup()
  t.end()
})

test('name-of-group-of-tests', function (t) {
  t.is(actual, expected, 'description of what this is testing')
  t.done()
})

test('cleanup', function (t) {
  cleanup()
  t.end()
})

If you need files on disk as part of your test, we use tacks to handle that, the boiler plate above with tacks looks like:

'use strict'
var path = require('path')
var test = require('tap').test
var common = require('../common-npm.js')
var Tacks = require('tacks')
var File = Tacks.File
var Dir = Tacks.Dir
var Symlink = Tacks.Symlink
var testdir = path.join(__dirname, path.basename(__filename, '.js'))

var fixture = new Tacks(Dir({
  'package.json': File({
    name: 'my-example-package',
    version: '1.0.0'
  })
}))

function setup () {
  cleanup()
  fixture.create(testdir)
  …any other sync setup…
}

function cleanup () {
  …any other sync cleanup…
  fixture.remove(testdir)
}

test('setup', function (t) {
  setup()
  t.end()
})

test('name-of-group-of-tests', function (t) {
  t.is(actual, expected, 'description of what this is testing')
  t.done()
})

test('cleanup', function (t) {
  cleanup()
  t.end()
})

If you're going to run npm commands (which unless you're writing a unit test, you will be), you do that as below, where you provide the npm command line as the first argument. Note that you almost always need a test directory to run commands like this from as you don't want to end up acting on npm's modules.

test('name-of-group-of-tests', function (t) {
  common.npm(['install', '--argument=value', 'package'], {cwd: testdir}, function (err, code, stdout, stderr) {
    if (err) throw err
    if (stdout.trim()) t.comment(stdout.trim())
    if (stderr.trim()) t.comment(stderr.trim())
    t.is(code, 0, 'brief desc of what our npm command was supposed to do')
    t.match(stdout, /some expected result/, 'got description of expected result')
    t.done()
  })
})

If you need to mock modules (by modules I mean anything you require), you can use require-inject.

Using it looks like:

test('name-of-group-of-tests', function (t) {
  var gentlyRm = requireInject('../../path/to/module/being/tested.js', {
    'mocked-module': {…mocked version…}
    '../../path/to/mocked/module.js': {…mocked version…}
  })
})

IMPORTANT: If you want to write unit tests for a function in any module that requires lib/npm.js you will need to call npm.load before requiring your module. A common way of doing this is:

var npm = require('../../lib/npm.js')

test('setup', function (t) {
  npm.load({}, t.end)
})
test('name-of-group-of-tests', function (t) {
  var myModule = require('../../lib/my-module.js')
  
})
Clone this wiki locally