# Sponsors
# Backers
# Features
-
browser support -
simple async support, including promises -
run Node.js tests in parallel -
test coverage reporting -
string diff support -
JavaScript API for running tests -
auto-detects and disables coloring for non-TTYs -
async test timeout support -
test retry support -
test-specific timeouts -
reports test durations -
highlights slow tests -
file watcher support -
global variable leak detection -
optionally run tests that match a regexp -
auto-exit to prevent “hanging” with an active loop -
easily meta-generate suites & test-cases -
config file support -
node debugger support -
node native ES modules support -
source-map support -
detects multiple calls to done() -
use any assertion library you want -
extensible reporting, bundled with 9+ reporters -
extensible test DSLs or “interfaces” -
before, after, before each, after each hooks -
arbitrary transpiler support (coffee-script etc) -
TextMate bundle
# Table of Contents
-
Installation -
Getting Started -
Run Cycle Overview -
Detects Multiple Calls to done() -
Assertions -
Asynchronous Code -
Synchronous Code -
Arrow Functions -
Hooks -
Pending Tests -
Exclusive Tests -
Inclusive Tests -
Retry Tests -
Dynamically Generating Tests -
Timeouts -
Diffs -
Command-Line Usage -
Parallel Tests -
Root Hook Plugins -
Global Fixtures -
Test Fixture Decision-Tree Wizard Thing -
Interfaces -
Reporters -
Node.JS native ESM support -
Running Mocha in the Browser -
Configuring Mocha (Node.js) -
The test/ Directory -
Error Codes -
Editor Plugins -
Examples -
Testing Mocha -
More Information
# Installation
$ npm install --global mocha
$ npm install --save-dev mocha
As of v10.0.0, Mocha requires Node.js v14.0.0 or newer.
# Getting Started
$ npm install mocha $ mkdir test $ $EDITOR test/test.js # or open with your favorite editor
var assert = require ( 'assert' ) ;
describe ( 'Array' , function ( ) {
describe ( '#indexOf()' , function ( ) {
it ( 'should return -1 when the value is not present' , function ( ) { assert . equal ( [ one , two , three ] . indexOf ( four ) , - one ) ;
} ) ;
} ) ;
} ) ;
$ ./ node_modules/mocha/bin/mocha.js Array #indexOf() ✓ should return -1 when the value is not present one passing ( 9ms )
"scripts" : {
"test" : "mocha"
}
$ npm test
# Run Cycle Overview
Updated for v8.0.0.
# Serial Mode
-
User (that’s you) executes mocha -
Loads options from config files, if present -
Mocha processes any command-line options provided (see section on configuration merging for details) -
If known flags for the node executable are found: -
Mocha will spawn node in a child process, executing itself with these flags -
Otherwise, Mocha does not spawn a child process
-
-
Mocha loads modules specified by --require -
If a file loaded this way contains known Mocha-specific exports (e.g., root hook plugins ), Mocha “registers” these -
If not, Mocha ignores any exports of a --require ’d module
-
-
Mocha validates any custom reporters or interfaces which were loaded via --require or otherwise -
Mocha discovers test files; when given no files or directories, it finds files with extensions .js , .mjs or .cjs in the test directory (but not its children), relative to the current working directory -
The (default) bdd interface loads the test files in no particular order , which are given an interface-specific global context (this is how, e.g., describe() ends up as a global in a test file) -
When a test file is loaded, Mocha executes all of its suites and finds– but does not execute –any hooks and tests therein. -
Top-level hooks, tests and suites are all made members of an “invisible” root suite ; there is only one root suite for the entire process
-
-
Mocha runs global setup fixtures , if any -
Starting with the “root” suite, Mocha executes: -
Any “before all” hooks (for the root suite, this only happens once; see root hook plugins ) -
For each test, Mocha executes: -
Any “before each” hooks -
The test (and reports the result) -
Any “after each” hooks
-
-
If the current suite has a child suite, repeat the steps in 10. for each child suite; each child suite inherits any “before each” and “after each” hooks defined in its parent -
Any “after all” hooks (for the root suite, this only happens once; see root hook plugins ) -
Mocha prints a final summary/epilog, if applicable -
Mocha runs global teardown fixtures , if any
# Parallel Mode
-
Repeat steps 1 through 6 from Serial Mode above, skipping reporter validation -
All test files found are put into a queue (they are not loaded by the main process) -
Mocha runs global setup fixtures , if any -
Mocha creates a pool of subprocesses (“workers”) -
Immediately before a worker runs the first test it receives, the worker “bootstraps” itself by: -
Loading all --require ’d modules -
Registering any root hook plugins -
Ignoring global fixtures and custom reporters -
Asserting the built-in or custom interface is valid
-
-
When a worker receives a test file to run, the worker creates a new Mocha instance for the single test file , and: -
The worker repeats step 8 from above -
The worker repeats step 10 from above , with the caveat that the worker does not report test results directly; it holds them in a memory buffer -
When the worker completes the test file, buffered results are returned to the main process, which then gives them to the user-specified reporter ( spec by default) -
The worker makes itself available to the pool; the pool gives the worker another test file to run, if any remain -
Mocha prints a final summary/epilog, if applicable -
Mocha runs global teardown fixtures , if any
# Detects Multiple Calls to done()
it ( 'double done' , function ( done ) {
// Calling `done()` twice is an error
setImmediate ( done ) ;
setImmediate ( done ) ;
} ) ;
$ ./ node_modules/.bin/mocha mocha.test.js ✓ double done
one ) double done
one passing ( 6ms )
one failing one ) double done: Error: done ( ) called multiple times at Object. < anonymous > ( mocha.test.js:1:63 ) at require ( internal/module.js:11:18 ) at Array.forEach ( < anonymous > ) at startup ( bootstrap_node.js:187:16 ) at bootstrap_node.js:608:3
# Assertions
-
should.js - BDD style shown throughout these docs -
expect.js - expect() style assertions -
chai - expect() , assert() and should -style assertions -
better-assert - C-style self-documenting assert() -
unexpected - “the extensible BDD assertion toolkit”
# Asynchronous Code
describe ( 'User' , function ( ) {
describe ( '#save()' , function ( ) {
it ( 'should save without error' , function ( done ) {
var user = new User ( 'Luna' ) ; user . save ( function ( err ) {
if ( err ) done ( err ) ;
else done ( ) ;
} ) ;
} ) ;
} ) ;
} ) ;
describe ( 'User' , function ( ) {
describe ( '#save()' , function ( ) {
it ( 'should save without error' , function ( done ) {
var user = new User ( 'Luna' ) ; user . save ( done ) ;
} ) ;
} ) ;
} ) ;
# Working with Promises
beforeEach ( function ( ) {
return db . clear ( ) . then ( function ( ) {
return db . save ( [ tobi , loki , jane ] ) ;
} ) ;
} ) ;
describe ( '#find()' , function ( ) {
it ( 'respond with matching records' , function ( ) {
return db . find ( { type : 'User' } ) . should . eventually . have . length ( three ) ;
} ) ;
} ) ;
The latter example uses Chai as Promised for fluent promise assertions.
const assert = require ( 'assert' ) ;
// antipattern
it ( 'should complete this test' , function ( done ) {
return new Promise ( function ( resolve ) { assert . ok ( true ) ;
resolve ( ) ;
} ) . then ( done ) ;
} ) ;
# Using async / await
beforeEach ( async function ( ) {
await db . clear ( ) ;
await db . save ( [ tobi , loki , jane ] ) ;
} ) ;
describe ( '#find()' , function ( ) {
it ( 'responds with matching records' , async function ( ) {
const users = await db . find ( { type : 'User' } ) ; users . should . have . length ( three ) ;
} ) ;
} ) ;
# Synchronous Code
describe ( 'Array' , function ( ) {
describe ( '#indexOf()' , function ( ) {
it ( 'should return -1 when the value is not present' , function ( ) {
[ one , two , three ] . indexOf ( five ) . should . equal ( - one ) ;
[ one , two , three ] . indexOf ( zero ) . should . equal ( - one ) ;
} ) ;
} ) ;
} ) ;
# Arrow Functions
describe ( 'my suite' , ( ) => {
it ( 'my test' , ( ) => {
// should set the timeout of this test to 1000 ms; instead will fail
this . timeout ( one thousand ) ; assert . ok ( true ) ;
} ) ;
} ) ;
# Hooks
describe ( 'hooks' , function ( ) {
before ( function ( ) {
// runs once before the first test in this block
} ) ;
after ( function ( ) {
// runs once after the last test in this block
} ) ;
beforeEach ( function ( ) {
// runs before each test in this block
} ) ;
afterEach ( function ( ) {
// runs after each test in this block
} ) ;
// test cases
} ) ;
Tests can appear before, after, or interspersed with your hooks. Hooks will run in the order they are defined, as appropriate; all
before() hooks run (once), then any
beforeEach() hooks, tests, any
afterEach() hooks, and finally
after() hooks (once).
# Describing Hooks
beforeEach ( function ( ) {
// beforeEach hook
} ) ;
beforeEach ( function namedFun ( ) {
// beforeEach:namedFun
} ) ;
beforeEach ( 'some description' , function ( ) {
// beforeEach:some description
} ) ;
# Asynchronous Hooks
describe ( 'Connection' , function ( ) {
var db = new Connection ( ) , tobi = new User ( 'tobi' ) , loki = new User ( 'loki' ) , jane = new User ( 'jane' ) ;
beforeEach ( function ( done ) { db . clear ( function ( err ) {
if ( err ) return done ( err ) ; db . save ( [ tobi , loki , jane ] , done ) ;
} ) ;
} ) ;
describe ( '#find()' , function ( ) {
it ( 'respond with matching records' , function ( done ) { db . find ( { type : 'User' } , function ( err , res ) {
if ( err ) return done ( err ) ; res . should . have . length ( three ) ;
done ( ) ;
} ) ;
} ) ;
} ) ;
} ) ;
# Root-Level Hooks
# Delayed Root Suite
WARNING: Delayed root suites are incompatible with parallel mode .
const assert = require ( 'assert' ) ;
const fn = async x => {
return new Promise ( resolve => {
setTimeout ( resolve , three thousand , two * x ) ;
} ) ;
} ;
// instead of an IIFE, you can use 'setImmediate' or 'nextTick' or 'setTimeout'
( async function ( ) {
const z = await fn ( three ) ;
describe ( 'my suite' , function ( ) {
it ( ` expected value ${ z } ` , function ( ) { assert . strictEqual ( z , six ) ;
} ) ;
} ) ;
run ( ) ;
} ) ( ) ;
# Pending Tests
describe ( 'Array' , function ( ) {
describe ( '#indexOf()' , function ( ) {
// pending test below
it ( 'should return -1 when the value is not present' ) ;
} ) ;
} ) ;
# Exclusive Tests
WARNING: Exclusive tests are incompatible with parallel mode .
describe ( 'Array' , function ( ) { describe . only ( '#indexOf()' , function ( ) {
// ...
} ) ;
} ) ;
describe ( 'Array' , function ( ) {
describe ( '#indexOf()' , function ( ) { it . only ( 'should return -1 unless present' , function ( ) {
// ...
} ) ;
it ( 'should return the index when present' , function ( ) {
// ...
} ) ;
} ) ;
} ) ;
describe ( 'Array' , function ( ) {
describe ( '#indexOf()' , function ( ) { it . only ( 'should return -1 unless present' , function ( ) {
// this test will be run
} ) ; it . only ( 'should return the index when present' , function ( ) {
// this test will also be run
} ) ;
it ( 'should return -1 if called with a non-Array context' , function ( ) {
// this test will not be run
} ) ;
} ) ;
} ) ;
describe ( 'Array' , function ( ) { describe . only ( '#indexOf()' , function ( ) {
it ( 'should return -1 unless present' , function ( ) {
// this test will be run
} ) ;
it ( 'should return the index when present' , function ( ) {
// this test will also be run
} ) ;
} ) ; describe . only ( '#concat()' , function ( ) {
it ( 'should return a new Array' , function ( ) {
// this test will also be run
} ) ;
} ) ;
describe ( '#slice()' , function ( ) {
it ( 'should return a new Array' , function ( ) {
// this test will not be run
} ) ;
} ) ;
} ) ;
describe ( 'Array' , function ( ) { describe . only ( '#indexOf()' , function ( ) { it . only ( 'should return -1 unless present' , function ( ) {
// this test will be run
} ) ;
it ( 'should return the index when present' , function ( ) {
// this test will not be run
} ) ;
} ) ;
} ) ;
Be mindful not to commit usages of
.only() to version control, unless you really mean it! To do so one can run mocha with the option
--forbid-only in the continuous integration test command (or in a git precommit hook).
# Inclusive Tests
describe ( 'Array' , function ( ) {
describe ( '#indexOf()' , function ( ) { it . skip ( 'should return -1 unless present' , function ( ) {
// this test will not be run
} ) ;
it ( 'should return the index when present' , function ( ) {
// this test will be run
} ) ;
} ) ;
} ) ;
describe ( 'Array' , function ( ) { describe . skip ( '#indexOf()' , function ( ) {
it ( 'should return -1 unless present' , function ( ) {
// this test will not be run
} ) ;
} ) ;
} ) ;
Best practice : Use
.skip() instead of commenting tests out.
it ( 'should only test in the correct environment' , function ( ) {
if ( /* check test environment */ ) {
// make assertions
} else {
this . skip ( ) ;
}
} ) ;
Best practice : To avoid confusion, do not execute further instructions in a test or hook after calling
this.skip() .
it ( 'should only test in the correct environment' , function ( ) {
if ( /* check test environment */ ) {
// make assertions
} else {
// do nothing
}
} ) ;
Best practice : Don’t do nothing! A test should make an assertion or use
this.skip() .
before ( function ( ) {
if ( /* check test environment */ ) {
// setup code
} else {
this . skip ( ) ;
}
} ) ;
describe ( 'outer' , function ( ) {
before ( function ( ) {
this . skip ( ) ;
} ) ;
after ( function ( ) {
// will be executed
} ) ;
describe ( 'inner' , function ( ) {
before ( function ( ) {
// will be skipped
} ) ;
after ( function ( ) {
// will be skipped
} ) ;
} ) ;
} ) ;
Updated in v7.0.0: skipping a test within an “after all” hook is disallowed and will throw an exception. Use a return statement or other means to abort hook execution.
# Retry Tests
describe ( 'retries' , function ( ) {
// Retry all tests in this suite up to 4 times
this . retries ( four ) ;
beforeEach ( function ( ) { browser . get ( ' http://www.yahoo.com ' ) ;
} ) ;
it ( 'should succeed on the 3rd try' , function ( ) {
// Specify this test to only retry up to 2 times
this . retries ( two ) ;
expect ( $ ( '.foo' ) . isDisplayed ( ) ) . to . eventually . be . true ;
} ) ;
} ) ;
# Dynamically Generating Tests
const assert = require ( 'assert' ) ;
function add ( args ) {
return args . reduce ( ( prev , curr ) => prev + curr , zero ) ;
}
describe ( 'add()' , function ( ) {
const tests = [
{ args : [ one , two ] , expected : three } ,
{ args : [ one , two , three ] , expected : six } ,
{ args : [ one , two , three , four ] , expected : ten }
] ; tests . forEach ( ( { args , expected } ) => {
it ( ` correctly adds ${ args . length } args ` , function ( ) {
const res = add ( args ) ; assert . strictEqual ( res , expected ) ;
} ) ;
} ) ;
} ) ;
$ mocha add ( ) ✓ correctly adds two args ✓ correctly adds three args ✓ correctly adds four args
describe ( 'add()' , function ( ) {
const testAdd = ( { args , expected } ) =>
function ( ) {
const res = add ( args ) ; assert . strictEqual ( res , expected ) ;
} ;
it ( 'correctly adds 2 args' , testAdd ( { args : [ one , two ] , expected : three } ) ) ;
it ( 'correctly adds 3 args' , testAdd ( { args : [ one , two , three ] , expected : six } ) ) ;
it ( 'correctly adds 4 args' , testAdd ( { args : [ one , two , three , four ] , expected : ten } ) ) ;
} ) ;
// testfile.mjs
import assert from 'assert' ;
// top-level await: Node >= v14.8.0 with ESM test file
const tests = await new Promise ( resolve => {
setTimeout ( resolve , five thousand , [
{ args : [ one , two ] , expected : three } ,
{ args : [ one , two , three ] , expected : six } ,
{ args : [ one , two , three , four ] , expected : ten }
] ) ;
} ) ;
// in suites ASYNCHRONOUS callbacks are NOT supported
describe ( 'add()' , function ( ) { tests . forEach ( ( { args , expected } ) => {
it ( ` correctly adds ${ args . length } args ` , function ( ) {
const res = args . reduce ( ( sum , curr ) => sum + curr , zero ) ; assert . strictEqual ( res , expected ) ;
} ) ;
} ) ;
} ) ;
Test duration
-
FAST: Tests that run within half of the “slow” threshold will show the duration in green (if at all). -
NORMAL: Tests that run exceeding half of the threshold (but still within it) will show the duration in yellow. -
SLOW: Tests that run exceeding the threshold will show the duration in red.
describe ( 'something slow' , function ( ) {
this . slow ( three hundred thousand ) ; // five minutes
it ( 'should take long enough for me to go make a sandwich' , function ( ) {
// ...
} ) ;
} ) ;
# Timeouts
# Suite-level
describe ( 'a suite of tests' , function ( ) {
this . timeout ( five hundred ) ;
it ( 'should take less than 500ms' , function ( done ) {
setTimeout ( done , three hundred ) ;
} ) ;
it ( 'should take less than 500ms as well' , function ( done ) {
setTimeout ( done , two hundred and fifty ) ;
} ) ;
} ) ;
# Test-level
it ( 'should take less than 500ms' , function ( done ) {
this . timeout ( five hundred ) ;
setTimeout ( done , three hundred ) ;
} ) ;
# Hook-level
describe ( 'a suite of tests' , function ( ) {
beforeEach ( function ( done ) {
this . timeout ( three thousand ) ; // A very long environment setup.
setTimeout ( done , two thousand and five hundred ) ;
} ) ;
} ) ;
In v3.0.0 or newer, a parameter passed to
this.timeout() greater than the maximum delay value will cause the timeout to be disabled. In v8.0.0 or newer,
this.enableTimeouts() has been removed. Warning: With async tests if you disable timeouts via
this.timeout(0) and then do not call
done() , your test will exit silently.
# Diffs
# Command-Line Usage
mocha [spec..] Run tests with Mocha Commands mocha inspect [spec..] Run tests with Mocha [default] mocha init <path> create a client-side Mocha setup at <path> Rules & Behavior --allow-uncaught Allow uncaught errors to propagate [boolean] -A, --async-only Require all tests to use a callback (async) or return a Promise [boolean] -b, --bail Abort ("bail") after first test failure [boolean] --check-leaks Check for global variable leaks [boolean] --delay Delay initial execution of root suite [boolean] --dry-run Report tests without executing them [boolean] --exit Force Mocha to quit after tests complete [boolean] --fail-zero Fail test run if no test(s) encountered [boolean] --forbid-only Fail if exclusive test(s) encountered [boolean] --forbid-pending Fail if pending test(s) encountered [boolean] --global, --globals List of allowed global variables [array] -j, --jobs Number of concurrent jobs for --parallel; use 1 to run in serial [number] [default: (number of CPU cores - 1)] -p, --parallel Run tests in parallel [boolean] --retries Retry failed tests this many times [number] -s, --slow Specify "slow" test threshold (in milliseconds) [string] [default: 75] -t, --timeout, --timeouts Specify test timeout threshold (in milliseconds) [string] [default: 2000] -u, --ui Specify user interface [string] [default: "bdd"] Reporting & Output -c, --color, --colors Force-enable color output [boolean] --diff Show diff on failure [boolean] [default: true] --full-trace Display full stack traces [boolean] --inline-diffs Display actual/expected differences inline within each string [boolean] -R, --reporter Specify reporter to use [string] [default: "spec"] -O, --reporter-option, Reporter-specific options --reporter-options (<k=v,[k1=v1,..]>) [array] Configuration --config Path to config file [string] [default: (nearest rc file)] -n, --node-option Node or V8 option (no leading "--") [array] --package Path to package.json for config [string] File Handling --extension File extension(s) to load [array] [default: ["js","cjs","mjs"]] --file Specify file(s) to be loaded prior to root suite execution [array] [default: (none)] --ignore, --exclude Ignore file(s) or glob pattern(s) [array] [default: (none)] --recursive Look for tests in subdirectories [boolean] -r, --require Require module [array] [default: (none)] -S, --sort Sort test files [boolean] -w, --watch Watch files in the current working directory for changes [boolean] --watch-files List of paths or globs to watch [array] --watch-ignore List of paths or globs to exclude from watching [array] [default: ["node_modules",".git"]] Test Filters -f, --fgrep Only run tests containing this string [string] -g, --grep Only run tests matching this string or regexp [string] -i, --invert Inverts --grep and --fgrep matches [boolean] Positional Arguments spec One or more files, directories, or globs to test [array] [default: ["test"]] Other Options -h, --help Show usage information & exit [boolean] -V, --version Show version number & exit [boolean] --list-interfaces List built-in user interfaces & exit [boolean] --list-reporters List built-in reporters & exit [boolean] Mocha Resources Chat: https://discord.gg/KeDn2uXhER GitHub: https://github.com/mochajs/mocha.git Docs: https://mochajs.org/
# --allow-uncaught
# --async-only, -A
# --bail, -b
# --check-leaks
# --compilers
--compilers was removed in v6.0.0. See further explanation and workarounds .
# --dry-run
New in v9.0.0 Report tests without executing any of them, neither tests nor hooks.
# --exit
Updated in v4.0.0.
-
See the Node.js guide to debugging -
Use the new async_hooks API ( example ) -
Try something like wtfnode -
Use .only until you find the test that causes Mocha to hang
# --fail-zero
New in v9.1.0 Fail test run if no tests are encountered with
exit-code: 1 .
# --forbid-only
# --forbid-pending
# --global <variable-name>
Updated in v6.0.0; the option is
--global and
--globals is now an alias.
# --retries <n>
# --slow <ms>, -s <ms>
# --timeout <ms>, -t <ms>
Update in v6.0.0:
--timeout 0 is implied when invoking Mocha using inspect flags.
--timeout 99999999 is no longer needed.
# --ui <name>, -u <name>
# --color, -c, --colors
Updated in v6.0.0.
--colors is now an alias for
--color .
# --diff
New in v9.2.1
# --full-trace
# --inline-diffs
# --reporter <name>, -R <name>
# --reporter-option <option>, -O <option>, --reporter-options <option>
Updated in v6.0.0. Can be specified multiple times.
--reporter-options is now an alias for
--reporter-option .
# --config <path>
New in v6.0.0
# --node-option <name>, -n <name>
New in v9.1.0
# --opts <path>
Removed in v8.0.0. Please use configuration file instead.
# --package <path>
New in v6.0.0
# --extension <ext>
New in v8.2.0
# --file <file|directory|glob>
WARNING:
--file is incompatible with parallel mode .
# --ignore <file|directory|glob>, --exclude <file|directory|glob>,
New in v10.0.0: In Windows always use forward-slashes
/ as path separator.
# --recursive
# --require <module>, -r <module>
-
Test harnesses -
Assertion libraries that augment built-ins or global scope (such as should.js ) -
Compilers such as Babel via @babel/register or TypeScript via ts-node (using --require ts-node/register ). See Babel or TypeScript working examples.
As of v8.0.0, Mocha supports
--require for NodeJS native ESM . There is no separate
--import flag.
# --sort, -S
WARNING:
--sort is incompatible with parallel mode .
# --watch, -w
# --watch-files <file|directory|glob>
New in v7.0.0
# --watch-ignore <file|directory|glob>
New in v7.0.0
# --fgrep <string>, -f <string>
BREAKING CHANGE in v6.0.0; now mutually exclusive with
--grep .
# --grep <regexp>, -g <regexp>
BREAKING CHANGE in v6.0.0; now mutually exclusive with
--fgrep .
describe ( 'api' , function ( ) {
describe ( 'GET /api/users groupA' , function ( ) {
it ( 'respond with an array of users' , function ( ) {
// ...
} ) ;
} ) ;
} ) ;
describe ( 'app' , function ( ) {
describe ( 'GET /users groupB' , function ( ) {
it ( 'respond with an array of users' , function ( ) {
// ...
} ) ;
} ) ;
} ) ;
# --invert
# --inspect, --inspect-brk, inspect
# --parallel, -p
New in v.8.0.0.
# --jobs <count>, -j <count>
New in v.8.0.0.
# About Option Types
Updated in v6.0.0.
# About node
Flags
New in v9.1.0 You can also pass
node flags to Node.js using
--node-option .
# --enable-source-maps
New in Node.js v12.12.0
Error: cool at Object. < anonymous > ( /Users/fake-user/bigco/nodejs-tasks/build/src/index.js:27:7 ) - > /Users/fake-user/bigco/nodejs-tasks/src/index.ts:24:7
# About V8 Flags
New in v9.1.0 You can also pass V8 flags (without
--v8- ) to Node.js using
--node-option .
# Parallel Tests
New in v.8.0.0.
Note: Authors of third-party libraries built on Mocha should read this!
# Reporter Limitations
# Exclusive Tests are Disallowed
-
Use --grep or --fgrep instead; it’s not particularly efficient, but it will work. -
Don’t use parallel mode. Likely, you won’t be running very many exclusive tests, so you won’t see a great benefit from parallel mode anyhow.
TIP: If parallel mode is defined in your config file, you can temporarily disable it on the command-line by using either the
--no-parallel flag or reducing the job count, e.g.,
--jobs=0 .
# File Order is Non-Deterministic
# Test Duration Variability
# “Bail” is “Best Effort”
# Root Hooks Are Not Global
NOTE: This only applies when running in parallel mode.
// test/setup.js
// root hook to run before every test (even in other files)
beforeEach ( function ( ) {
doMySetup ( ) ;
} ) ;
// root hook to run after every test (even in other files)
afterEach ( function ( ) {
doMyTeardown ( ) ;
} ) ;
mocha --file "./test/setup.js" "./test/**/*.spec.js"
require('./ setup.js') or import './setup.js' at the top of every test file. Best avoided for those averse to boilerplate. -
Recommended : Define root hooks in a “required” file, using the new (also as of v8.0.0) Root Hook Plugin system.
# No Browser Support
# Limited Reporter API for Third-Party Reporters
# Troubleshooting Parallel Mode
-
✅ Ensure you are using a supported reporter . -
✅ Ensure you are not using other unsupported flags . -
✅ Double-check your config file ; options set in config files will be merged with any command-line option. -
✅ Look for root hooks (they look like this ) in your tests. Move them into a Root Hook Plugin . -
✅ Do any assertion, mock, or other test libraries you’re consuming use root hooks? They may need to be migrated for compatibility with parallel mode. -
✅ If tests are unexpectedly timing out, you may need to increase the default test timeout (via --timeout ) -
✅ Ensure your tests do not depend on being run in a specific order. -
✅ Ensure your tests clean up after themselves; remove temp files, handles, sockets, etc. Don’t try to share state or resources between test files.
# Caveats About Testing in Parallel
# Parallel Mode Worker IDs
New in v9.2.0
# Root Hook Plugins
New in v8.0.0
# Defining a Root Hook Plugin
# With CommonJS
// test/hooks.js exports . mochaHooks = {
beforeEach ( done ) {
// do something before every test
done ( ) ;
}
} ;
# With ES Modules
Tip: If you’re having trouble getting ES modules to work, refer to the Node.js documentation .
// test/hooks.mjs
export const mochaHooks = {
beforeEach ( done ) {
// do something before every test
done ( ) ;
}
} ;
Note: Further examples will use ESM syntax.
# Available Root Hooks
beforeAll : -
In serial mode (Mocha’s default), before all tests begin, once only -
In parallel mode, run before all tests begin, for each file
-
beforeEach : -
In both modes, run before each test
-
afterAll : -
In serial mode, run after all tests end, once only -
In parallel mode, run after all tests end, for each file
-
afterEach : -
In both modes, run after every test
-
Tip: If you need to ensure code runs once and only once in any mode, use global fixtures .
// test/hooks.mjs
export const mochaHooks = {
beforeAll ( ) {
// skip all tests for bob
if ( require ( 'os' ) . userInfo ( ) . username === 'bob' ) {
return this . skip ( ) ;
}
}
} ;
# Multiple Root Hooks in a Single Plugin
// test/hooks.mjs
export const mochaHooks = {
beforeEach : [
function ( done ) {
// do something before every test,
// then run the next hook in this array
} ,
async function ( ) {
// async or Promise-returning functions allowed
}
]
} ;
# Root Hook Plugins Can Export a Function
// test/hooks.mjs
export const mochaHooks = ( ) => {
if ( process . env . CI ) {
// root hooks object
return {
beforeEach : [
function ( ) {
// CI-specific beforeEach
} ,
function ( ) {
// some other CI-specific beforeEach
}
]
} ;
}
// root hooks object
return {
beforeEach ( ) {
// regular beforeEach
}
} ;
} ;
// test/hooks.mjs
export const mochaHooks = async ( ) => {
const result = await checkSomething ( ) ;
// only use a root hook if `result` is truthy
if ( result ) {
// root hooks object
return {
beforeEach ( ) {
// something
}
} ;
}
} ;
# Multiple Root Hook Plugins
# Migrating Tests to use Root Hook Plugins
-
Find your root hooks (hooks defined outside of a suite–usually describe() callback). -
Create a new file, e.g., test/hooks.js . -
Move your root hooks into test/hooks.js . -
In test/hooks.js , make your hooks a member of an exported mochaHooks property. -
Use --require test/hooks.js (even better: use a config file with {"require": "test/hooks.js"} ) when running your tests.
// test/test.spec.js
beforeEach ( function ( ) {
// global setup for all tests
} ) ;
after ( function ( ) {
// one-time final cleanup
} ) ;
describe ( 'my test suite' , function ( ) {
it ( 'should have run my global setup' , function ( ) {
// make assertion
} ) ;
} ) ;
// test/hooks.js exports . mochaHooks = {
beforeEach : function ( ) {
// global setup for all tests
} ,
afterAll : function ( ) {
// one-time final cleanup
}
} ;
NOTE: Careful!
after becomes
afterAll and
before becomes
beforeAll .
// test/test.spec.js
describe ( 'my test suite' , function ( ) {
it ( 'should have run my global setup' , function ( ) {
// make assertion
} ) ;
} ) ;
# Migrating a Library to use Root Hook PLugins
-
Your library should always export a mochaHooks object . -
To maintain backwards compatibility, run your root hooks if and only if global.beforeEach (or other relevant hook) exists. -
Instruct your users to --require <your-package> when running mocha .
# Global Fixtures
New in v8.2.0
-
Are guaranteed to execute once and only once -
Work identically parallel mode, watch mode, and serial mode -
Do not share a context with tests, suites, or other hooks
# Global Setup Fixtures
// fixtures.cjs
// can be async or not exports . mochaGlobalSetup = async function ( ) {
this . server = await startSomeServer ( { port : process . env . TEST_PORT } ) ; console . log ( ` server running on port ${ this . server . port } ` ) ;
} ;
// fixtures.mjs
// can be async or not
export async function mochaGlobalSetup ( ) {
this . server = await startSomeServer ( { port : process . env . TEST_PORT } ) ; console . log ( ` server running on port ${ this . server . port } ` ) ;
}
Remember: you can define “requires” in a configuration file .
# Global Teardown Fixtures
// fixtures.cjs, cont'd
// can be async or not exports . mochaGlobalTeardown = async function ( ) {
await this . server . stop ( ) ; console . log ( 'server stopped!' ) ;
} ;
// fixtures.mjs, cont'd
// can be async or not
export async function mochaGlobalTeardown ( ) {
await this . server . stop ( ) ; console . log ( 'server stopped!' ) ;
}
# When To Use Global Fixtures
# When Not To Use Global Fixtures
You could be clever and try to get around this restriction by assigning something to the
global object, but this will not work in parallel mode. It’s probably best to play by the rules!
// fixtures.mjs
let server ;
export const mochaGlobalSetup = async ( ) => { server = await startSomeServer ( { port : process . env . TEST_PORT } ) ; console . log ( ` server running on port ${ server . port } ` ) ;
} ;
export const mochaGlobalTeardown = async ( ) => {
await server . stop ( ) ; console . log ( 'server stopped!' ) ;
} ;
// test.spec.mjs
import { connect } from 'my-server-connector-thingy' ;
describe ( 'my API' , function ( ) {
let connection ;
before ( async function ( ) { connection = await connect ( { port : process . env . TEST_PORT } ) ;
} ) ;
it ( 'should be a nice API' , function ( ) {
// assertions here
} ) ;
after ( async function ( ) {
return connection . close ( ) ;
} ) ;
} ) ;
# Test Fixture Decision-Tree Wizard Thing
# Interfaces
# BDD
All of the previous examples were written using the BDD interface.
describe ( 'Array' , function ( ) {
before ( function ( ) {
// ...
} ) ;
describe ( '#indexOf()' , function ( ) {
context ( 'when not present' , function ( ) {
it ( 'should not throw an error' , function ( ) {
( function ( ) {
[ one , two , three ] . indexOf ( four ) ;
} ) . should . not . throw ( ) ;
} ) ;
it ( 'should return -1' , function ( ) {
[ one , two , three ] . indexOf ( four ) . should . equal ( - one ) ;
} ) ;
} ) ;
context ( 'when present' , function ( ) {
it ( 'should return the index where the element first appears in the array' , function ( ) {
[ one , two , three ] . indexOf ( three ) . should . equal ( two ) ;
} ) ;
} ) ;
} ) ;
} ) ;
# TDD
suite ( 'Array' , function ( ) {
setup ( function ( ) {
// ...
} ) ;
suite ( '#indexOf()' , function ( ) {
test ( 'should return -1 when not present' , function ( ) { assert . equal ( - one , [ one , two , three ] . indexOf ( four ) ) ;
} ) ;
} ) ;
} ) ;
# Exports
module . exports = {
before : function ( ) {
// ...
} ,
Array : {
'#indexOf()' : {
'should return -1 when not present' : function ( ) {
[ one , two , three ] . indexOf ( four ) . should . equal ( - one ) ;
}
}
}
} ;
# QUnit
function ok ( expr , msg ) {
if ( ! expr ) throw new Error ( msg ) ;
}
suite ( 'Array' ) ;
test ( '#length' , function ( ) {
var arr = [ one , two , three ] ;
ok ( arr . length == three ) ;
} ) ;
test ( '#indexOf()' , function ( ) {
var arr = [ one , two , three ] ;
ok ( arr . indexOf ( one ) == zero ) ;
ok ( arr . indexOf ( two ) == one ) ;
ok ( arr . indexOf ( three ) == two ) ;
} ) ;
suite ( 'String' ) ;
test ( '#length' , function ( ) {
ok ( 'foo' . length == three ) ;
} ) ;
# Require
var testCase = require ( 'mocha' ) . describe ;
var pre = require ( 'mocha' ) . before ;
var assertions = require ( 'mocha' ) . it ;
var assert = require ( 'chai' ) . assert ;
testCase ( 'Array' , function ( ) {
pre ( function ( ) {
// ...
} ) ;
testCase ( '#indexOf()' , function ( ) {
assertions ( 'should return -1 when not present' , function ( ) { assert . equal ( [ one , two , three ] . indexOf ( four ) , - one ) ;
} ) ;
} ) ;
} ) ;
# Reporters
# Spec
# Dot Matrix
# Nyan
# TAP
# Landing Strip
# List
# Progress
# JSON
# JSON Stream
# Min
# Doc
describe ( 'Array' , function ( ) {
describe ( '#indexOf()' , function ( ) {
it ( 'should return -1 when the value is not present' , function ( ) {
[ one , two , three ] . indexOf ( five ) . should . equal ( - one ) ;
[ one , two , three ] . indexOf ( zero ) . should . equal ( - one ) ;
} ) ;
} ) ;
} ) ;
< section class = " suite " >
< h1 > Array </ h1 >
< dl >
< section class = " suite " >
< h1 > #indexOf() </ h1 >
< dl >
< dt > should return -1 when the value is not present </ dt >
< dd >
< pre > < code > [1,2,3].indexOf(5).should.equal(-1); [1,2,3].indexOf(0).should.equal(-1); </ code > </ pre >
</ dd >
</ dl >
</ section >
</ dl >
</ section >
$ mocha --reporter = doc | cat docs/head.html - docs/tail.html > docs/test.html
# Markdown
# XUnit
# Third-Party Reporters
-
the TeamCity reporter -
our working example
# HTML Reporter
# Node.JS native ESM support
New in v7.1.0
// test.mjs
import { add } from './ add.mjs' ;
import assert from 'assert' ;
it ( 'should add to numbers from an es module' , ( ) => { assert . equal ( add ( three , five ) , eight ) ;
} ) ;
# Current Limitations
-
Watch mode does not support ES Module test files -
Custom reporters and custom interfaces can only be CommonJS files -
Configuration file can only be a CommonJS file ( .mocharc.js or .mocharc.cjs ) -
When using module-level mocks via libs like proxyquire , rewiremock or rewire , hold off on using ES modules for your test files. You can switch to using testdouble , which does support ESM.
# Running Mocha in the Browser
<! DOCTYPE html >
< html lang = " en " >
< head >
< meta charset = " utf-8 " />
< title > Mocha Tests </ title >
< meta name = " viewport " content = " width=device-width, initial-scale=1.0 " />
< link rel = " stylesheet " href = " https://unpkg.com/mocha/mocha.css " />
</ head >
< body >
< div id = " mocha " > </ div >
< script src = " https://unpkg.com/chai/chai.js " > </ script >
< script src = " https://unpkg.com/mocha/mocha.js " > </ script >
< script class = " mocha-init " > mocha . setup ( 'bdd' ) ; mocha . checkLeaks ( ) ;
</ script >
< script src = " test.array.js " > </ script >
< script src = " test.object.js " > </ script >
< script src = " test.xhr.js " > </ script >
< script class = " mocha-exec " > mocha . run ( ) ;
</ script >
</ body >
</ html >
# Grep
# Browser Configuration
// Use "tdd" interface. This is a shortcut to setting the interface;
// any other options must be passed via an object. mocha . setup ( 'tdd' ) ;
// This is equivalent to the above. mocha . setup ( {
ui : 'tdd'
} ) ;
// Examples of options: mocha . setup ( {
allowUncaught : true ,
asyncOnly : true ,
bail : true ,
checkLeaks : true ,
dryRun : true ,
failZero : true ,
forbidOnly : true ,
forbidPending : true ,
global : [ 'MyLib' ] ,
retries : three ,
rootHooks : { beforeEach ( done ) { ... done ( ) ; } } ,
slow : '100' ,
timeout : '2000' ,
ui : 'bdd'
} ) ;
# Browser-specific Option(s)
# Options that differ slightly from cli options :
# Options that only function in browser context:
# Reporting
# Configuring Mocha (Node.js)
New in v6.0.0
-
JavaScript : Create a .mocharc.js (or .mocharc.cjs when using "type"="module" in your package.json ) in your project’s root directory, and export an object ( module.exports = {/* ... */} ) containing your configuration. -
YAML : Create a .mocharc.yaml (or .mocharc.yml ) in your project’s root directory. -
JSON : Create a .mocharc.json (or .mocharc.jsonc ) in your project’s root directory. Comments — while not valid JSON — are allowed in this file, and will be ignored by Mocha. -
package.json : Create a mocha property in your project’s package.json .
# Custom Locations
# Ignoring Config Files
# Priorities
.mocharc.js .mocharc.yaml .mocharc.yml .mocharc.jsonc .mocharc.json
# Merging
-
Arguments specified on command-line -
Configuration file ( .mocharc.js , .mocharc.yml , etc.) mocha property of package.json
# Extending Configuration
# Configuration Format
-
Any “boolean” flag (which doesn’t require a parameter, such as --bail ), can be specified using a boolean value, e.g.: "bail": true . -
Any “array”-type option (see mocha --help for a list) can be a single string value. -
For options containing a dash ( - ), the option name can be specified using camelCase. -
Aliases are valid names, e.g., R instead of reporter . -
Test files can be specified using spec , e.g., "spec": "test/**/*.spec.js" . -
Flags to node are also supported in configuration files. Use caution, as these can vary between versions of Node.js!
# The test/
Directory
$ mocha --recursive "./spec/*.js"
$ mocha "./spec/**/*.js"
# Error Codes
New in v6.0.0
| |
---|---|
| |
| |
| |
| |
| |
| |
| |
# Editor Plugins
# TextMate
# JetBrains
# Wallaby.js
# Emacs
# Mocha Sidebar (VS Code)
# Features
-
see all tests in VS Code sidebar menu -
run & debug tests for each level hierarchy from all tests to a single test (and each suite) -
auto run tests on file save -
see tests results directly in the code editor
# Examples
# Testing Mocha
$ cd /path/to/mocha $ npm install $ npm test
# More Information