Advanced Usage

These methods are primarily for internal use, but can be handy in some unusual situations. If you find yourself using them frequently, you may be Doing It Wrong. However, if you find them useful, you should feel perfectly comfortable using them.

Please let us know if you frequently encounter situations requiring advanced usage, because this may indicate a shortcoming in the "non-advanced" API.

Class: t.Spawn()

Similar to the Test class, but instead of a callback that gets a object with assertion methods, it starts a child process and parses its output.

Class: t.Stdin()

Similar to the Test class, but instead of a callback that gets a object with assertion methods, it reads the process standard input, and parses that as TAP-formatted data.

t.counts

This is an object with counters representing the number of pass, fail, todo, skip, and total assertions made by this test and any subtests, primarily for use in reporting.

Fields:

  • t.counts.total
  • t.counts.pass
  • t.counts.fail
  • t.counts.skip
  • t.counts.todo

t.lists

This is an object with lists of the failed, todo, and skip assertions in this test and any subtests, primarily for use in reporting.

Fields:

  • t.lists.fail
  • t.lists.todo
  • t.lists.skip

t.stdin()

Parse standard input as if it was a child test named /dev/stdin.

Returns a Promise which resolves with the parent when the input stream is completed.

This is primarily for use in the test runner, so that you can do some-tap-emitting-program | tap other-file.js - -Rnyan.

If no name argument is provided, then a default name of /dev/stdin will be used.

t.stdinOnly()

Parse standard input without wrapping it in a child test.

This is only allowed if the test object has no other children and has printed no assertions. Once engaged, any attempt to use normal test methods will throw an error. It only exists to support piping a TAP stream into the tap executable for reporting, which is a very specialized use case.

t.spawn(command, arguments, [options], [name])

Sometimes, instead of running a child test directly inline, you might want to run a TAP producting test as a child process, and treat its standard output as the TAP stream.

Returns a Promise which resolves with the parent when the child process is completed.

That's what this method does.

It is primarily used by the executable runner, to run all of the filename arguments provided on the command line.

If no name argument is provided, then a default name will be created based on the command and arguments.

The options object is passed to child_process.spawn, and can contain stuff like stdio directives and environment vars. It's also where you put the same fields that would be passed to any assertion or child test:

  • bail: Set to true to bail out on the first failure. This is done by checking the output and then forcibly killing the process, but also sets the TAP_BAIL environment variable, which node-tap uses to set this field internally as well.
  • timeout: The number of ms to allow the child process to continue. If it goes beyond this time, the child process will be forcibly killed.
  • todo Set to boolean true or a String to mark this as pending.
  • skip Set to boolean true or a String to mark this as skipped.
  • bail Set to boolean true to bail out on the first test failure.
  • diagnostic Set to true to show a yaml diagnostic block even if the test passes. Set to false to never show a yaml diagnostic block.
  • buffered Set to true to run as a buffered subtest. Set to false to run as an indented subtest. The default is false unless TAP_BUFFER=1 is set in the environment.
  • strict Treat invalid TAP output as an error. node-tap will never produce invalid TAP output, but this is useful when spawning child tests as subprocesses.

t.addAssert(name, length, fn)

This is used for creating assertion methods on the Test class.

It's a little bit advanced, but it's also super handy sometimes. All of the assert methods below are created using this function, and it can be used to create application-specific assertions in your tests.

The name is the method name that will be created. The length is the number of arguments the assertion operates on. (The message and extra arguments will always be appended to the end.)

For example, you could have a file at test/setup.js that does the following:

const t = require('tap')

// convenience
if (module === require.main) {
  t.pass('ok')
  return
}

// Add an assertion that a string is in Title Case
// It takes one argument (the string to be tested)
t.Test.prototype.addAssert('titleCase', 1, function (str, message, extra) {
  message = message || 'should be in Title Case'
  // the string in Title Case
  // A fancier implementation would avoid capitalizing little words
  // to get `Silence of the Lambs` instead of `Silence Of The Lambs`
  // But whatever, it's just an example.
  const tc = str.toLowerCase().replace(/\b./, match => match.toUpperCase())

  // should always return another assert call, or
  // this.pass(message) or this.fail(message, extra)
  return this.equal(str, tc, message, extra)
})

Then in your individual tests, you'd do this:

require('./setup.js') // adds the assert
const t = require('tap')
t.titleCase('This Passes')
t.titleCase('however, tHis tOTaLLy faILS')

t.endAll()

Call the end() method on all child tests, and then on this one.

t.assertAt, t.assertStack, extra.at, extra.stack

The Test object will try to work out the most useful stack and at options to tell you where a failing assertion was made.

In very rare and interesting cases, you may wish to override this for some reason. For example, you may be wrapping tap.Test object methods, and wish to show the user where they called your method, rather than showing where your method called into tap.

You can do this in two possible ways:

  1. Set the at and/or stack properties on the extra object passed to assert methods.
  2. Set the t.assertAt and/or t.assertStack properties on the Test object immediately before calling the assertion method. The values are consumed and deleted when the next assertion is called.

The at property should be an object with the following properties at minimum:

  • file - The file name where the assertion is called
  • line - The line number where the assertion is called

The stack property should be a string stack trace similar to those found on Error objects.

For best results, calculate these values using the stack-utils module.