Mocha is a feature-rich JavaScript test framework running onNode.js and in the browser, making asynchronous testingsimple andfun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases. Hosted onGitHub.
# Sponsors
Use Mocha at Work? Ask your manager or marketing team if they’d helpsupport our project. Your company’s logo will also be displayed onnpmjs.com and ourGitHub repository.
# Backers
Find Mocha helpful? Become abacker and support Mocha with a monthly donation.
# 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
Install withnpm globally:
$npminstall--global mocha
or as a development dependency for your project:
$npminstall --save-dev mocha
As of v10.0.0, Mocha requires Node.js v14.0.0 or newer.
# Getting Started
$npminstall mocha$mkdirtest$$EDITOR test/test.js# or open with your favorite editor
In your editor:
var assert=require('assert');describe('Array',function(){describe('#indexOf()',function(){it('should return -1 when the value is not present',function(){ assert.equal([1,2,3].indexOf(4),-1);});});});
Back in the terminal:
$ ./node_modules/mocha/bin/mocha.js Array#indexOf() ✓ shouldreturn-1 when the value is not present1 passing(9ms)
Set up a test script in package.json:
"scripts":{"test":"mocha"}
Then run tests with:
$npmtest
# Run Cycle Overview
Updated for v8.0.0.
The following is a mid-level outline of Mocha’s “flow of execution” when run in Node.js; the “less important” details have been omitted.
In a browser, test files are loaded by<script>
tags, and callingmocha.run()
begins at step 9below.
# Serial Mode
- User (that’s you) executes
mocha
- Loads options from config files, if present
- Mocha processes any command-line options provided (see section onconfiguration 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 will spawn
- 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 - Mochadiscovers test files; when given no files or directories, it finds files with extensions
.js
,.mjs
or.cjs
in thetest
directory (but not its children), relative to the current working directory - The (default)bdd interface loads the test filesin 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 onlyone root suite for the entire process
- Mocha runsglobal setup fixtures, if any
- Starting with the “root” suite, Mocha executes:
- Any “before all” hooks (for theroot suite, this only happens once; seeroot 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 suiteinherits any “before each” and “after each” hooks defined in its parent
- Any “after all” hooks (for theroot suite, this only happens once; seeroot hook plugins)
- Mocha prints a final summary/epilog, if applicable
- Mocha runsglobal teardown fixtures, if any
# Parallel Mode
- Repeat steps 1 through 6 fromSerial Mode above, skipping reporter validation
- All test files found are put into a queue (they arenot loaded by the main process)
- Mocha runsglobal 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
- Loading all
- When a worker receives a test file to run, the worker creates a new Mocha instancefor the single test file, and:
- The worker repeats step 8 fromabove
- The worker repeats step 10 fromabove, with the caveat that the workerdoes 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 runsglobal teardown fixtures, if any
# Detects Multiple Calls todone()
If you use callback-based async tests, Mocha will throw an error ifdone()
is called multiple times. This is handy for catching accidental double callbacks.
it('double done',function(done){// Calling `done()` twice is an errorsetImmediate(done);setImmediate(done);});
Running the above test will give you the below error message:
$ ./node_modules/.bin/mocha mocha.test.js ✓ doubledone1) doubledone1 passing(6ms)1 failing1) double done: Error: done() called multipletimes 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
Mocha allows you to use any assertion library you wish. In the above example, we’re using Node.js’ built-inassert module — but generally, if it throws anError
, it will work! This means you can use libraries such as:
- should.js - BDD style shown throughout these docs
- expect.js -
expect()
style assertions - chai -
expect()
,assert()
andshould
-style assertions - better-assert - C-style self-documenting
assert()
- unexpected - “the extensible BDD assertion toolkit”
# Asynchronous Code
By adding an argument (usually nameddone
) toit()
to a test callback, Mocha will know that it should wait for this function to be called to complete the test. This callback accepts both anError
instance (or subclass thereof)or a falsy value; anything else is invalid usage and throws an error (usually causing a failed test).
describe('User',function(){describe('#save()',function(){it('should save without error',function(done){var user=newUser('Luna'); user.save(function(err){if(err)done(err);elsedone();});});});});
Alternatively, use thedone()
callback directly (which will handle an error argument, if it exists):
describe('User',function(){describe('#save()',function(){it('should save without error',function(done){var user=newUser('Luna'); user.save(done);});});});
# Working with Promises
Alternately, instead of using thedone()
callback, you may return aPromise. This is useful if the APIs you are testing return promises instead of taking callbacks:
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(3);});});
The latter example usesChai as Promised for fluent promise assertions.
In Mocha v3.0.0 and newer, returning aPromise
and callingdone()
will result in an exception, as this is generally a mistake:
const assert=require('assert');// antipatternit('should complete this test',function(done){returnnewPromise(function(resolve){ assert.ok(true);resolve();}).then(done);});
The above test will fail withError: Resolution method is overspecified. Specify a callback *or* return a Promise; not both.
. In versions older than v3.0.0, the call todone()
is effectively ignored.
# Using async / await
If your JS environment supportsasync / await, you can also write asynchronous tests like this:
beforeEach(asyncfunction(){await db.clear();await db.save([tobi, loki, jane]);});describe('#find()',function(){it('responds with matching records',asyncfunction(){const users=await db.find({type:'User'}); users.should.have.length(3);});});
# Limitations of asynchronous callbacks
You can use all asynchronous callbacks (done
,Promise
, andasync
/await
) in callbacks forit()
,before()
,after()
,beforeEach()
,afterEach()
) but notdescribe()
– it must be synchronous.See#5046 for more information.
# Synchronous Code
When testing synchronous code, omit the callback and Mocha will automatically continue on to the next test.
describe('Array',function(){describe('#indexOf()',function(){it('should return -1 when the value is not present',function(){[1,2,3].indexOf(5).should.equal(-1);[1,2,3].indexOf(0).should.equal(-1);});});});
# Arrow Functions
Passingarrow functions (aka “lambdas”) to Mocha is discouraged. Lambdas lexically bindthis
and cannot access the Mocha context. For example, the following code will fail:
describe('my suite',()=>{it('my test',()=>{// should set the timeout of this test to 1000 ms; instead will failthis.timeout(1000); assert.ok(true);});});
If you do not need to use Mocha’s context, lambdas should work. Be aware that using lambdas will be more painful to refactor if the need eventually arises!
Alternatively, you can override certain context variables, such as test timeouts, by chain-calling methods of the created tests and/or hooks:
describe('my suite',()=>{beforeEach(()=>{}).timeout(1000);it('my test',()=>{ assert.ok(true);}).timeout(1000);}).timeout(1000);
# Hooks
With its default “BDD”-style interface, Mocha provides the hooksbefore()
,after()
,beforeEach()
, andafterEach()
. These should be used to set up preconditions and clean up after your tests.
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 anybeforeEach()
hooks, tests, anyafterEach()
hooks, and finallyafter()
hooks (once).
# Describing Hooks
Any hook can be invoked with an optional description, making it easier to pinpoint errors in your tests. If a hook is given a named function, that name will be used if no description is supplied.
beforeEach(function(){// beforeEach hook});beforeEach(functionnamedFun(){// beforeEach:namedFun});beforeEach('some description',function(){// beforeEach:some description});
# Asynchronous Hooks
All hooks (before()
,after()
,beforeEach()
,afterEach()
) may be sync or async as well, behaving much like a regular test-case. For example, you may wish to populate database with dummy content before each test:
describe('Connection',function(){var db=newConnection(), tobi=newUser('tobi'), loki=newUser('loki'), jane=newUser('jane');beforeEach(function(done){ db.clear(function(err){if(err)returndone(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)returndone(err); res.should.have.length(3);done();});});});});
# Root-Level Hooks
A hook defined at the top scope of a test file (outside of a suite) is aroot hook.
As of v8.0.0,Root Hook Plugins are the preferred mechanism for setting root hooks.
# Delayed Root Suite
WARNING: Delayed root suites are incompatible withparallel mode.
If you need to perform asynchronous operations before any of your suites are run (e.g. for dynamically generating tests), you may delay the root suite. Runmocha
with the--delay
flag. This will attach a special callback function,run()
, to the global context:
const assert=require('assert');constfn=asyncx=>{returnnewPromise(resolve=>{setTimeout(resolve,3000,2* x);});};// instead of an IIFE, you can use 'setImmediate' or 'nextTick' or 'setTimeout'(asyncfunction(){const z=awaitfn(3);describe('my suite',function(){it(`expected value${z}`,function(){ assert.strictEqual(z,6);});});run();})();
# Pending Tests
“Pending” — as in “someone should write these test cases eventually” — test-cases are thosewithout a callback:
describe('Array',function(){describe('#indexOf()',function(){// pending test belowit('should return -1 when the value is not present');});});
Pending tests will be included in the test results, and marked as pending. A pending test is not considered a failed test.
Read theinclusive tests section for an example of conditionally marking a test as pending viathis.skip()
.
# Exclusive Tests
WARNING: Exclusive tests are incompatible withparallel mode.
The exclusivity feature allows you to runonly the specified suite or test-caseby appending.only()
to the function. Here’s an example of executing only a particular suite:
describe('Array',function(){ describe.only('#indexOf()',function(){// ...});});
Note: All nested suites will still be executed.
Here’s an example of executing an individual test case:
describe('Array',function(){describe('#indexOf()',function(){ it.only('should return -1 unless present',function(){// ...});it('should return the index when present',function(){// ...});});});
Previous to v3.0.0,.only()
used string matching to decide which tests to execute; this is no longer the case. In v3.0.0 or newer,.only()
can be used multiple times to define a subset of tests to run:
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});});});
You may also choose multiple suites:
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});});});
Buttests will have precedence:
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});});});
Note: Hooks, if present, will still be executed.
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
This feature is the inverse of.only()
. By appending.skip()
, you may tell Mocha to ignore test case(s). Anything skipped will be marked aspending, and reported as such. Here’s an example of skipping an individual test:
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});});});
You can also put.skip()
on an entire suite. This is equivalent to appending.skip()
onto all tests in the suite. Hooks in the suite are also skipped.
describe('Array',function(){ describe.skip('#indexOf()',function(){it('should return -1 unless present',function(){// this test will not be run});});});
Note: Code in skipped suites, that is placed outside of hooks or tests is still executed, as mocha will still invoke the suite function to build up the suite structure for visualization.
Best practice: Use
.skip()
instead of commenting tests out.
You may also skipat runtime usingthis.skip()
. If a test needs an environment or configuration which cannot be detected beforehand, a runtime skip is appropriate. For example:
it('should only test in the correct environment',function(){if(/* check test environment */){// make assertions}else{this.skip();}});
The above test will be reported aspending. It’s also important to note that callingthis.skip()
will effectivelyabort the test.
Best practice: To avoid confusion, do not execute further instructions in a test or hook after calling
this.skip()
.
Contrast the above test with the following code:
it('should only test in the correct environment',function(){if(/* check test environment */){// make assertions}else{// do nothing}});
Because this testdoes nothing, it will be reported aspassing.
Best practice: Don’t do nothing! A test should make an assertion or use
this.skip()
.
To skipmultiple tests in this manner, usethis.skip()
in a “before all” hook:
before(function(){if(/* check test environment */){// setup code}else{this.skip();}});
This will skip allit
,beforeEach/afterEach
, anddescribe
blocks within the suite.before/after
hooks are skipped unless they are defined at the same level as the hook containingthis.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.
Before Mocha v3.0.0,this.skip()
was not supported in asynchronous tests and hooks.
# Retry Tests
You can choose to retry failed tests up to a certain number of times. This feature is designed to handle end-to-end tests (functional tests/Selenium…) where resources cannot be easily mocked/stubbed.It’s not recommended to use this feature for unit tests.
This feature does re-run a failed test and its correspondingbeforeEach/afterEach
hooks, but notbefore/after
hooks.this.retries()
has no effect on failing hooks.
NOTE: Example below was written using Selenium webdriver (whichoverwrites global Mocha hooks forPromise
chain).
describe('retries',function(){// Retry all tests in this suite up to 4 timesthis.retries(4);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 timesthis.retries(2);expect($('.foo').isDisplayed()).to.eventually.be.true;});});
# Dynamically Generating Tests
Given Mocha’s use of function expressions to define suites and test cases, it’s straightforward to generate your tests dynamically. No special syntax is required — plain ol’ JavaScript can be used to achieve functionality similar to “parameterized” tests, which you may have seen in other frameworks.
Take the following example:
const assert=require('assert');functionadd(args){return args.reduce((prev, curr)=> prev+ curr,0);}describe('add()',function(){const tests=[{args:[1,2],expected:3},{args:[1,2,3],expected:6},{args:[1,2,3,4],expected:10}]; tests.forEach(({args, expected})=>{it(`correctly adds${args.length} args`,function(){const res=add(args); assert.strictEqual(res, expected);});});});
The above code will produce a suite with three specs:
$ mocha add() ✓ correctly adds2 args ✓ correctly adds3 args ✓ correctly adds4 args
Tests added inside a.forEach
handler often don’t play well with editor plugins, especially with “right-click run” features.Another way to parameterize tests is to generate them with a closure. This following example is equivalent to the one above:
describe('add()',function(){consttestAdd=({args, expected})=>function(){const res=add(args); assert.strictEqual(res, expected);};it('correctly adds 2 args',testAdd({args:[1,2],expected:3}));it('correctly adds 3 args',testAdd({args:[1,2,3],expected:6}));it('correctly adds 4 args',testAdd({args:[1,2,3,4],expected:10}));});
Withtop-level await
you can collect your test data in a dynamic and asynchronous way while the test file is being loaded.
See also--delay
for CommonJS modules withouttop-level await
.
// testfile.mjsimport assertfrom'assert';// top-level await: Node >= v14.8.0 with ESM test fileconst tests=awaitnewPromise(resolve=>{setTimeout(resolve,5000,[{args:[1,2],expected:3},{args:[1,2,3],expected:6},{args:[1,2,3,4],expected:10}]);});// in suites ASYNCHRONOUS callbacks are NOT supporteddescribe('add()',function(){ tests.forEach(({args, expected})=>{it(`correctly adds${args.length} args`,function(){const res= args.reduce((sum, curr)=> sum+ curr,0); assert.strictEqual(res, expected);});});});
Test duration
Many reporters will display test duration and flag tests that are slow (default: 75ms), as shown here with the SPEC reporter:
There are three levels of test duration (depicted in the following image):
- 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.
To tweak what’s considered “slow”, you can use theslow()
method:
describe('something slow',function(){this.slow(300000);// five minutesit('should take long enough for me to go make a sandwich',function(){// ...});});
# Timeouts
# Suite-level
Suite-level timeouts may be applied to entire test “suites”, or disabled viathis.timeout(0)
. This will be inherited by all nested suites and test-cases that do not override the value.
describe('a suite of tests',function(){this.timeout(500);it('should take less than 500ms',function(done){setTimeout(done,300);});it('should take less than 500ms as well',function(done){setTimeout(done,250);});});
# Test-level
Test-specific timeouts may also be applied, or the use ofthis.timeout(0)
to disable timeouts all together:
it('should take less than 500ms',function(done){this.timeout(500);setTimeout(done,300);});
# Hook-level
Hook-level timeouts may also be applied:
describe('a suite of tests',function(){beforeEach(function(done){this.timeout(3000);// A very long environment setup.setTimeout(done,2500);});});
Again, usethis.timeout(0)
to disable the timeout for a hook.
In v3.0.0 or newer, a parameter passed to
this.timeout()
greater than themaximum 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 viathis.timeout(0)
and then do not calldone()
, your test will exit silently.
# Diffs
Mocha supports theerr.expected
anderr.actual
properties of any thrownAssertionError
s from an assertion library. Mocha will attempt to display the difference between what was expected, and what the assertion actually saw. Here’s an example of a “string” diff using--inline-diffs
:
# Command-Line Usage
mocha [spec..]Run tests with MochaCommands 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] --pass-on-failing-test-suite Not fail test run if tests were failed [boolean] [default: false] --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
By default, Mocha will attempt to trap uncaught exceptions thrown from running tests and report these as test failures. Use--allow-uncaught
to disable this behavior and allow uncaught exceptions to propagate. Will typically cause the process to crash.
This flag is useful when debugging particularly difficult-to-track exceptions.
#--async-only, -A
Enforce a rule that tests must be written in “async” style, meaning each test provides adone
callback or returns aPromise
. Non-compliant tests will be marked as failures.
#--bail, -b
Causes Mocha to stop running tests after the first test failure it encounters. Corresponding “after each” and “after all” hooks are executed for potential cleanup.
--bail
doesnot imply--exit
.
#--check-leaks
Use this option to have Mocha check for global variables that are leaked while running tests. Specify globals that are acceptable via the--global
option (for example:--check-leaks --global jQuery --global MyLib
).
#--compilers
--compilers
was removed in v6.0.0. Seefurther 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.
TL;DR: If your tests hang after an upgrade to Mocha v4.0.0 or newer, use--exit
for a quick (though not necessarily recommended) fix.
Prior to version v4.0.0,by default, Mocha would force its own process to exit once it was finished executing all tests. This behavior enables a set of potential problems; it’s indicative of tests (or fixtures, harnesses, code under test, etc.) which don’t clean up after themselves properly. Ultimately, “dirty” tests can (but not always) lead tofalse positive orfalse negative results.
“Hanging” most often manifests itself if a server is still listening on a port, or a socket is still open, etc. It can also be something like a runawaysetInterval()
, or even an errantPromise
that never fulfilled.
Thedefault behavior in v4.0.0 (and newer) is--no-exit
, where previously it was--exit
.
The easiest way to “fix” the issue is to pass--exit
to the Mocha process. Itcan be time-consuming to debug — because it’s not always obvious where the problem is — but itis recommended to do so.
To ensure your tests aren’t leaving messes around, here are some ideas to get started:
- See theNode.js guide to debugging
- Use the new
async_hooks
API (example) - Try something likewtfnode
- Use
.only
until you find the test that causes Mocha to hang
#--pass-on-failing-test-suite
New in v10.7.0
If set totrue
, Mocha returns exit code0
even if there are failed tests during run.
#--fail-zero
New in v9.1.0
Fail test run if no tests are encountered withexit-code: 1
.
#--forbid-only
Enforce a rule that tests may not be exclusive (use of e.g.,describe.only()
orit.only()
is disallowed).
--forbid-only
causes Mocha to fail when an exclusive (“only’d”) test or suite is encountered, and it will abort further test execution.
#--forbid-pending
Enforce a rule that tests may not be skipped (use of e.g.,describe.skip()
,it.skip()
, orthis.skip()
anywhere is disallowed).
--forbid-pending
causes Mocha to fail when a skipped (“pending”) test or suite is encountered, and it will abort further test execution.
#--global <variable-name>
Updated in v6.0.0; the option is
--global
and--globals
is now an alias.
Define a global variable name. For example, suppose your app deliberately exposes a global namedapp
andYUI
, you may want to add--global app --global YUI
.
--global
accepts wildcards. You could do--global '*bar'
and it would matchfoobar
,barbar
, etc. You can also pass in'*'
to ignore all globals.
--global
can accept a comma-delimited list;--global app,YUI
is equivalent to--global app --global YUI
.
By using this option in conjunction with--check-leaks
, you can specify a whitelist of known global variables that youexpect to leak into global scope.
#--retries <n>
Retries failed testsn
times.
Mocha does not retry test failures by default.
#--slow <ms>, -s <ms>
Specify the “slow” test threshold in milliseconds. Mocha uses this to highlight test cases that are taking too long. “Slow” tests are not considered failures.
Note: A test that executes forhalf of the “slow” time will be highlightedin yellow with the defaultspec
reporter; a test that executes for entire “slow” time will be highlightedin red.
#--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.
Specifies the test case timeout, defaulting to two (2) seconds (2000 milliseconds). Tests taking longer than this amount of time will be marked as failed.
To override you may pass the timeout in milliseconds, or a value with thes
suffix, e.g.,--timeout 2s
and--timeout 2000
are equivalent.
To disable timeouts, use--timeout 0
.
Note: synchronous (blocking) tests are also bound by the timeout, but they will not complete until the code stops blocking. Infinite loops will still be infinite loops!
#--ui <name>, -u <name>
The--ui
option lets you specify the interface to use, defaulting tobdd
.
#--color, -c, --colors
Updated in v6.0.0.
--colors
is now an alias for--color
.
“Force” color output to be enabled, or alternatively force it to be disabled via--no-color
. By default, Mocha uses thesupports-color module to decide.
In some cases, color output will be explicitly suppressed by certain reporters outputting in a machine-readable format.
#--diff
When possible, show the difference between expected and actual values when an assertion failure is encountered.
This flag is unusual in that itdefaults totrue
; use--no-diff
to suppress Mocha’s own diff output.
Some assertion libraries will supply their own diffs, in which case Mocha’s will not be used, regardless of the default value.
Mocha’s own diff output does not conform to any known standards, and is designed to be human-readable.
New in v9.2.1
By default strings are truncated to 8192 characters before generating a diff. This is to prevent performance problems with large strings.
It can however make the output harder to interpret when comparing large strings. Therefore it is possible to configure this value using--reporter-option maxDiffSize=[number]
.
A value of 0 indicates no limit, default is 8192 characters.
#--full-trace
Enable “full” stack traces. By default, Mocha attempts to distill stack traces into less noisy (though still useful) output.
This flag is helpful when debugging a suspected issue within Mocha or Node.js itself.
#--inline-diffs
Enable “inline” diffs, an alternative output for diffing strings.
Useful when working with large strings.
Does nothing if an assertion library supplies its own diff output.
#--reporter <name>, -R <name>
Specify the reporter that will be used, defaulting tospec
.
Allows use of third-party reporters. For example,mocha-lcov-reporter may be used with--reporter mocha-lcov-reporter
after it has been installed.
#--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
.
Provide options specific to a reporter in<key>=<value>
format, e.g.,--reporter tap --reporter-option tapVersion=13
.
Not all reporters accept options.
Can be specified as a comma-delimited list.
#--config <path>
New in v6.0.0
Specify an explicit path to aconfiguration file.
By default, Mocha will search for a config file if--config
is not specified; use--no-config
to suppress this behavior.
#--node-option <name>, -n <name>
New in v9.1.0
For Node.js and V8 options. Mocha forwards these options to Node.js by spawning a new child-process.
The options are set without leading dashes--
, e.g.-n require=foo -n unhandled-rejections=strict
Can also be specified as a comma-delimited list:-n require=foo,unhandled-rejections=strict
#--opts <path>
Removed in v8.0.0. Please useconfiguration file instead.
#--package <path>
New in v6.0.0
Specify an explicit path to apackage.json
file (ostensibly containing configuration in amocha
property).
By default, Mocha looks for apackage.json
in the current working directory or nearest ancestor, and will use the first file found (regardless of whether it contains amocha
property); to suppresspackage.json
lookup, use--no-package
.
#--extension <ext>
Files having this extension will be considered test files. Defaults tojs
.
Specifying--extension
willremove.js
as a test file extension; use--extension js
to re-add it. For example, to load.mjs
and.js
test files, you must supply--extension mjs --extension js
.
The option can be given multiple times. The option accepts a comma-delimited list:--extension a,b
is equivalent to--extension a --extension b
.
New in v8.2.0
--extension
now supports multipart extensions (e.g.,spec.js
), leading dots (.js
) and combinations thereof (.spec.js
);
#--file <file>
WARNING:
--file
is incompatible withparallel mode.
Explicitlyinclude a test file to be loaded before other test files. Multiple uses of--file
are allowed, and will be loaded in order given.
Useful if you want to declare, for example, hooks to be run before every test across all other test files.
Files specified this way are not affected by--sort
or--recursive
.
Files specified in this way should contain one or more suites, tests or hooks. If this is not the case, consider--require
instead.
#--ignore <file|directory|glob>, --exclude <file|directory|glob>,
Explicitly ignore one or more test files, directories or globs (e.g.,some/**/files*
) that would otherwise be loaded.
Can be specified multiple times.
New in v10.0.0: In Windows always use forward-slashes
/
as path separator.
Files specified using--file
are not affected by this option.
#--recursive
When looking for test files, recurse into subdirectories.
See--extension
for defining which files are considered test files.
#--require <module>, -r <module>
Require a module before loading the user interface or test files. This is useful for:
- Test harnesses
- Assertion libraries that augment built-ins or global scope (such asshould.js)
- Compilers such as Babel via@babel/register or TypeScript viats-node (using
--require ts-node/register
). SeeBabel orTypeScript working examples.
Modules required in this manner are expected to do work synchronously; Mocha won’t wait for async tasks in a required module to finish.
You cannot use--require
to set hooks. If you want to set hooks to run, e.g., before each test, use aRoot Hook Plugin.
As of v8.0.0, Mocha supports
--require
forNodeJS native ESM. There is no separate--import
flag.
#--sort, -S
WARNING:
--sort
is incompatible withparallel mode.
Sort test files (by absolute path) usingArray.prototype.sort.
#--watch, -w
Rerun tests on file changes.
The--watch-files
and--watch-ignore
options can be used to control which files are watched for changes.
Tests may be rerun manually by typing ⓡ ⓢ ⏎ (same shortcut asnodemon
).
#--watch-files <file|directory|glob>
New in v7.0.0
List of paths or globs to watch when--watch
is set. If a file matching the given glob changes or is added or removed mocha will rerun all tests.
If the path is a directory all files and subdirectories will be watched.
By default all files in the current directory having one of the extensions provided by--extension
and not contained in thenode_modules
or.git
folders are watched.
The option can be given multiple times. The option accepts a comma-delimited list:--watch-files a,b
is equivalent to--watch-files a --watch-files b
#--watch-ignore <file|directory|glob>
New in v7.0.0
List of paths or globs to exclude from watching. Defaults tonode_modules
and.git
.
To exclude all files in a directory it is preferable to usefoo/bar
instead offoo/bar/**/*
. The latter will still watch the directoryfoo/bar
but will ignore all changes to the content of that directory.
The option can be given multiple times. The option accepts a comma-delimited list:--watch-ignore a,b
is equivalent to--watch-ignore a --watch-ignore b
#--fgrep <string>, -f <string>
BREAKING CHANGE in v6.0.0; now mutually exclusive with
--grep
.
Cause Mocha to only run tests having titles containing the givenstring
.
Mutually exclusive with--grep
.
#--grep <regexp>, -g <regexp>
BREAKING CHANGE in v6.0.0; now mutually exclusive with
--fgrep
.
Cause Mocha to only run tests matching the givenregexp
, which is internally compiled to aRegExp.
Suppose, for example, you have “api” related tests, as well as “app” related tests, as shown in the following snippet; One could use--grep api
or--grep app
to run one or the other. The same goes for any other part of a suite or test-case title,--grep users
would be valid as well, or even--grep GET
.
And another option with double quotes:--grep "groupA|groupB"
.
And for more complex criteria:--grep "/get/i"
. Some shells as e.g. Git-Bash-for-Windows may require:--grep "'/get/i'"
. Using flags other than theignoreCase /i
(especially/g
and/y
) may lead to unpredictable results.
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(){// ...});});});
Mutually exclusive with--fgrep
.
#--invert
Use theinverse of the match specified by--grep
orfgrep
.
Requires either--grep
or--fgrep
(but not both).
#--inspect, --inspect-brk, inspect
Enables Node.js’ inspector.
Use--inspect
/--inspect-brk
to launch the V8 inspector for use with Chrome Dev Tools.
Useinspect
to launch Node.js’ internal debugger.
All of these options are mutually exclusive.
Implies--timeout 0
.
#--parallel, -p
New in v.8.0.0.
Use the--parallel
flag to run tests in a worker pool.
Each test file will be put into a queue and executed as workers become available.
NOTICE:--parallel
has certain implications for Mocha’s behavior which you must be aware of. Read more aboutrunning tests in parallel.
#--jobs <count>, -j <count>
New in v.8.0.0.
Use--jobs <count>
to specify themaximum number of processes in the worker pool.
The default value is thenumber of CPU cores less 1.
Hint: Use--jobs 0
or--jobs 1
to temporarily disable--parallel
.
Has no effect unless used with--parallel
.
# About Option Types
Updated in v6.0.0.
Each flag annotated of type[boolean]
in Mocha’s--help
output can benegated by prepending--no-
to the flag name. For example,--no-color
will disable Mocha’s color output, which is enabled by default.
Unless otherwise noted,all boolean flags default tofalse
.
# Aboutnode
Flags
Themocha
executable supports all applicable flags which thenode
executable supports.
These flags vary depending on your version of Node.js.
node
flags can be defined in Mocha’sconfiguration.
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
If the--enable-source-maps
flagis passed to mocha, source maps will be collected and used to provide accurate stack traces for transpiled code:
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
Prepend--v8-
to any flag listed in the output ofnode --v8-options
(excluding--v8-options
itself) to use it.
V8 flags can be defined in Mocha’sconfiguration.
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.
Depending on the number and nature of your tests, you may find a significant performance benefit when running tests in parallel (using the--parallel
flag).
Parallel tests should work out-of-the box for many use cases. However, you must be aware of some important implications of the behavior.
Note: Authors of third-party libraries built on Mocha should read this!
# Reporter Limitations
Due to the nature of the following reporters, they cannot work when running tests in parallel:
These reporters expect Mocha to knowhow many tests it plans to run before execution. This information is unavailable in parallel mode, as test files are loaded only when they are about to be run.
In serial mode, tests results will “stream” as they occur. In parallel mode, reporter output isbuffered; reporting will occur after each file is completed. In practice, the reporter output will appear in “chunks” (but will otherwise be identical). If a test file is particularly slow, there may be a significant pause while it’s running.
# Exclusive Tests are Disallowed
You cannot useit.only
,describe.only
,this.only()
, etc., in parallel mode. This is for the same reason as the incompatible reporters noted above: in parallel mode, Mocha does not load all files and suites into memory before running tests.
Suggested workarounds:
- 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
In parallel mode, Mocha does not guarantee the order in which test files will run, nor which worker process runs them.
Because of this, the following options, which depend on order,cannot be used in parallel mode:
# Test Duration Variability
Running tests in parallel mode will naturally use more system resources. The OS may take extra time to schedule and complete some operations, depending on system load. For this reason, the timeouts ofindividual tests may need to be increased eitherglobally orotherwise.
# “Bail” is “Best Effort”
When used with--bail
(orthis.bail()
) to exit after the first failure, it’s likely other tests will be running at the same time. Mocha must shut down its worker processes before exiting.
Likewise, subprocesses may throw uncaught exceptions. When used with--allow-uncaught
, Mocha will “bubble” this exception to the main process, but still must shut down its processes.
Either way, Mocha will abort the test run “very soon.”
# Root Hooks Are Not Global
NOTE: This only applies when running in parallel mode.
Aroot hook is a hook in a test file which isnot defined within a suite. An example using thebdd
interface:
// 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();});
When run (in the default “serial” mode) via this command:
mocha--file"./test/setup.js""./test/**/*.spec.js"
setup.js
will be executedfirst, and install the two hooks shown above for every test found in./test/**/*.spec.js
.
The above example does not work in parallel mode.
When Mocha runs in parallel mode,test files do not share the same process, nor do they share the same instance of Mocha. Consequently, a hypothetical root hook defined in test fileAwill not be present in test fileB.
Here are a couple suggested workarounds:
require('./setup.js')
orimport './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 asof v8.0.0)Root Hook Plugin system.
If you need to run some codeonce and only once, use aglobalfixture instead.
# No Browser Support
Parallel mode is only available in Node.js, for now.
# Limited Reporter API for Third-Party Reporters
Third-party reporters may encounter issues when attempting to access non-existent properties withinTest
,Suite
, andHook
objects. If a third-party reporter does not work in parallel mode (but otherwise works in serial mode), pleasefile an issue.
# Troubleshooting Parallel Mode
If you find your tests don’t work properly when run with--parallel
, either shrug and move on, or use this handy-dandy checklist to get things working:
- ✅ Ensure you are using asupported reporter.
- ✅ Ensure you are not usingother unsupported flags.
- ✅ Double-check yourconfig file; options set in config files will be merged with any command-line option.
- ✅ Look for root hooks (they look likethis) in your tests. Move them into aRoot Hook Plugin.
- ✅ Do any assertion, mock, or other test libraries you’re consuming use root hooks? They may need to bemigrated 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
Some types of tests arenot so well-suited to run in parallel. For example, extremely timing-sensitive tests, or tests which make I/O requests to a limited pool of resources (such as opening ports, or automating browser windows, hitting a test DB, or remote server, etc.).
Free-tier cloud CI services may not provide a suitable multi-core container or VM for their build agents. Regarding expected performance gains in CI: your mileage may vary. It may help to use a conditional in a.mocharc.js
to check forprocess.env.CI
, and adjust the job count as appropriate.
It’s unlikely (but not impossible) to see a performance gain from ajob countgreater than the number of available CPU cores. That said,play around with the job count–there’s no one-size-fits all, and the unique characteristics of your tests will determine the optimal number of jobs; it may even be that fewer is faster!
# Parallel Mode Worker IDs
New in v9.2.0
Each process launched by parallel mode is assigned a unique id, from 0 for the first process to be launched, to N-1 for the Nth process. This worker id may be accessed in tests via the environment variableMOCHA_WORKER_ID
. It can be used for example to assign a different database, service port, etc for each test process.
# Root Hook Plugins
New in v8.0.0
In some cases, you may want ahook before (or after) every test in every file. These are calledroot hooks. Previous to v8.0.0, the way to accomplish this was to use--file
combined with root hooks (seeexample above). This still works in v8.0.0, butnot when running tests in parallel mode! For that reason, running root hooks using this method isstrongly discouraged, and may be deprecated in the future.
ARoot Hook Plugin is a JavaScript file loaded via--require
which “registers” one or more root hooks to be used across all test files.
In browsers you can set root hooks directly via arootHooks
object:mocha.setup({ rootHooks: {beforeEach() {...}} })
, seemocha.setup()
# Defining a Root Hook Plugin
A Root Hook Plugin file is a script which exports (viamodule.exports
) amochaHooks
property. It is loaded via--require <file>
.
Here’s a simple example which defines a root hook, written using CJS and ESM syntax.
# With CommonJS
// test/hooks.jsexports.mochaHooks={beforeEach(done){// do something before every testdone();}};
# With ES Modules
We’re using the.mjs
extension in these examples.
Tip: If you’re having trouble getting ES modules to work, refer tothe Node.js documentation.
// test/hooks.mjsexportconst mochaHooks={beforeEach(done){// do something before every testdone();}};
Note: Further examples will use ESM syntax.
# Available Root Hooks
Root hooks work with any interface, butthe property names do not change. In other words, if you are using thetdd
interface,suiteSetup
maps tobeforeAll
, andsetup
maps tobeforeEach
.
Available root hooks and their behavior:
beforeAll
:- Inserial mode (Mocha’s default),before all tests begin, once only
- Inparallel mode, runbefore all tests begin, for each file
beforeEach
:- Inboth modes, runbefore each test
afterAll
:- Inserial mode, runafter all tests end, once only
- Inparallel mode, runafter all tests end, for each file
afterEach
:- Inboth modes, runafter every test
Tip: If you need to ensure code runs once and only once in any mode, useglobal fixtures.
As with other hooks,this
refers to the current context object:
// test/hooks.mjsexportconst mochaHooks={beforeAll(){// skip all tests for bobif(require('os').userInfo().username==='bob'){returnthis.skip();}}};
# Multiple Root Hooks in a Single Plugin
Multiple root hooks can be defined in a single plugin, for organizational purposes. For example:
// test/hooks.mjsexportconst mochaHooks={beforeEach:[function(done){// do something before every test,// then run the next hook in this array},asyncfunction(){// async or Promise-returning functions allowed}]};
# Root Hook Plugins Can Export a Function
If you need to perform some logic–such as choosing a root hook conditionally, based on the environment–mochaHooks
can be afunction which returns the expected object.
// test/hooks.mjsexportconstmochaHooks=()=>{if(process.env.CI){// root hooks objectreturn{beforeEach:[function(){// CI-specific beforeEach},function(){// some other CI-specific beforeEach}]};}// root hooks objectreturn{beforeEach(){// regular beforeEach}};};
If you need to perform an async operation,mochaHooks
can bePromise
-returning:
// test/hooks.mjsexportconstmochaHooks=async()=>{const result=awaitcheckSomething();// only use a root hook if `result` is truthyif(result){// root hooks objectreturn{beforeEach(){// something}};}};
# Multiple Root Hook Plugins
Multiple root hook plugins can be registered by using--require
multiple times. For example, to register the root hooks inhooks-a.js
andhooks-b.js
, use--require hooks-a.js --require hooks-b.js
. These will be registered (and run)in order.
# Migrating Tests to use Root Hook Plugins
To migrate your tests using root hooks to a root hook plugin:
- Find your root hooks (hooks definedoutside 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 exportedmochaHooks
property. - Use
--require test/hooks.js
(even better: use aconfig file with{"require": "test/hooks.js"}
) when running your tests.
For example, given the following file,test/test.spec.js
, containing root hooks:
// test/test.spec.jsbeforeEach(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});});
Yourtest/hooks.js
(for this example, a CJS module) should contain:
// test/hooks.jsexports.mochaHooks={beforeEach:function(){// global setup for all tests},afterAll:function(){// one-time final cleanup}};
NOTE: Careful!
after
becomesafterAll
andbefore
becomesbeforeAll
.
Your originaltest/test.spec.js
should now contain:
// test/test.spec.jsdescribe('my test suite',function(){it('should have run my global setup',function(){// make assertion});});
Runningmocha --require test/hooks.js test/test.spec.js
will run as before (and is now ready to be used with--parallel
).
# Migrating a Library to use Root Hook PLugins
If you’re a library maintainer, and your library uses root hooks, you can migrate by refactoring your entry point:
- Your library shouldalways export a
mochaHooks
object. - To maintain backwards compatibility, run your root hooksif and only if
global.beforeEach
(or other relevant hook) exists. - Instruct your users to
--require <your-package>
when runningmocha
.
# Global Fixtures
New in v8.2.0
At first glance,global fixtures seem similar toroot hooks. However, unlike root hooks, global fixtures:
- Areguaranteed to executeonce and only once
- Work identically parallel mode, watch mode, and serial mode
- Do not share a context with tests, suites, or other hooks
There are two types of global fixtures:global setup fixtures andglobal teardown fixtures.
# Global Setup Fixtures
To create a global setup fixture, exportmochaGlobalSetup
from a script, e.g.,:
// fixtures.cjs// can be async or notexports.mochaGlobalSetup=asyncfunction(){this.server=awaitstartSomeServer({port: process.env.TEST_PORT}); console.log(`server running on port${this.server.port}`);};
…or an ES module:
// fixtures.mjs// can be async or notexportasyncfunctionmochaGlobalSetup(){this.server=awaitstartSomeServer({port: process.env.TEST_PORT}); console.log(`server running on port${this.server.port}`);}
To use it, load this file when running Mocha viamocha --require fixtures.cjs
(or whatever you have named the file).
Remember: you can define “requires” in aconfiguration file.
Now, before Mocha loads and runs your tests, it will execute the above global setup fixture, starting a server for testing. This won’t shutdown the server when Mocha is done, however! To do that, use aglobal teardown fixture.
# Global Teardown Fixtures
Just like aglobal setup fixture, aglobal teardown fixture can be created by exporting from a “required” script (we can put both types of fixtures in a single file):
// fixtures.cjs, cont'd// can be async or notexports.mochaGlobalTeardown=asyncfunction(){awaitthis.server.stop(); console.log('server stopped!');};
…or an ES module:
// fixtures.mjs, cont'd// can be async or notexportasyncfunctionmochaGlobalTeardown(){awaitthis.server.stop(); console.log('server stopped!');}
You’ll note that we usedthis
in the fixture examples. Global setup fixtures and global teardown fixturesshare a context, which means we can add properties to the context object (this
) in the setup fixture, and reference them later in the teardown fixture. This is more useful when the fixtures are in separate files, since you can just use JS’ variable scoping rules instead (example below).
As explainedabove–andbelow–test filesdo not have access to this context object.
# When To Use Global Fixtures
Global fixtures are good for spinning up a server, opening a socket, or otherwise creating a resource that your tests will repeatedly access via I/O.
# When Not To Use Global Fixtures
If you need to access an in-memory value (such as a file handle or database connection),don’t use global fixtures to do this, because your tests will not have access to the value.
You could be clever and try to get around this restriction by assigning something to the
global
object, but this willnot work in parallel mode. It’s probably best to play by the rules!
Instead, use the global fixture tostart the database, and useroot hook plugins or plain ol’hooks to create a connection.
Here’s an example of using global fixtures and “before all” hooks to get the job done. Note that we do not reference theserver
object anywhere in our tests!
First, use a global fixture to start and stop a test server:
// fixtures.mjslet server;exportconstmochaGlobalSetup=async()=>{ server=awaitstartSomeServer({port: process.env.TEST_PORT}); console.log(`server running on port${server.port}`);};exportconstmochaGlobalTeardown=async()=>{await server.stop(); console.log('server stopped!');};
Then, connect to the server in your tests:
// test.spec.mjsimport{connect}from'my-server-connector-thingy';describe('my API',function(){let connection;before(asyncfunction(){ connection=awaitconnect({port: process.env.TEST_PORT});});it('should be a nice API',function(){// assertions here});after(asyncfunction(){return connection.close();});});
Finally, use this command to bring it together:mocha --require fixtures.mjs test.spec.mjs
.
# Test Fixture Decision-Tree Wizard Thing
This flowchart will help you decide which ofhooks,root hook plugins orglobal fixtures you should use.
# Interfaces
Mocha’s “interface” system allows developers to choose their style of DSL. Mocha hasBDD,TDD,Exports,QUnit andRequire-style interfaces.
# BDD
TheBDD interface providesdescribe()
,context()
,it()
,specify()
,before()
,after()
,beforeEach()
, andafterEach()
.
context()
is just an alias fordescribe()
, and behaves the same way; it provides a way to keep tests easier to read and organized. Similarly,specify()
is an alias forit()
.
All of the previous examples were written using theBDD interface.
describe('Array',function(){before(function(){// ...});describe('#indexOf()',function(){context('when not present',function(){it('should not throw an error',function(){(function(){[1,2,3].indexOf(4);}).should.not.throw();});it('should return -1',function(){[1,2,3].indexOf(4).should.equal(-1);});});context('when present',function(){it('should return the index where the element first appears in the array',function(){[1,2,3].indexOf(3).should.equal(2);});});});});
# TDD
TheTDD interface providessuite()
,test()
,suiteSetup()
,suiteTeardown()
,setup()
, andteardown()
:
suite('Array',function(){setup(function(){// ...});suite('#indexOf()',function(){test('should return -1 when not present',function(){ assert.equal(-1,[1,2,3].indexOf(4));});});});
# Exports
TheExports interface allows for organizing tests in a modular fashion. It is particularly useful in larger projects where test suites can be segmented into different files.
Note: The Exports interface is not supported in browser environments. This limitation arises because browsers handle module exports differently from Node.js. If you intend to run tests in a browser, consider using the BDD or TDD interfaces, which are fully supported.
The Exports interface is much like Mocha’s predecessorexpresso. The keysbefore
,after
,beforeEach
, andafterEach
are special-cased, object values are suites, and function values are test-cases:
module.exports={before:function(){// ...},Array:{'#indexOf()':{'should return -1 when not present':function(){[1,2,3].indexOf(4).should.equal(-1);}}}};
# QUnit
TheQUnit-inspired interface matches the “flat” look of QUnit, where the test suite title is definedbefore the test-cases. Like TDD, it usessuite()
andtest()
, but resembling BDD, it also containsbefore()
,after()
,beforeEach()
, andafterEach()
.
functionok(expr, msg){if(!expr)thrownewError(msg);}suite('Array');test('#length',function(){var arr=[1,2,3];ok(arr.length==3);});test('#indexOf()',function(){var arr=[1,2,3];ok(arr.indexOf(1)==0);ok(arr.indexOf(2)==1);ok(arr.indexOf(3)==2);});suite('String');test('#length',function(){ok('foo'.length==3);});
# Require
Therequire
interface allows you to require thedescribe
and friend words directly usingrequire
and call them whatever you want. This interface is also useful if you want to avoid global variables in your tests.
Note: Therequire
interface cannot be run via thenode
executable, and must be run viamocha
.
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([1,2,3].indexOf(4),-1);});});});
# Reporters
Mocha reporters adjust to the terminal window, and always disable ANSI-escape coloring when the stdio streams are not associated with a TTY.
# Spec
Alias:Spec
,spec
This is the default reporter. The Spec reporter outputs a hierarchical view nested just as the test cases are.
# Dot Matrix
Alias:Dot
,dot
The Dot Matrix reporter is a series of characters which represent test cases. Failures highlight in red exclamation marks (!
), pending tests with a blue comma (,
), and slow tests as yellow. Good if you prefer minimal output.
# Nyan
Alias:Nyan
,nyan
The Nyan reporter is exactly what you might expect:
# TAP
Alias:TAP
,tap
The TAP reporter emits lines for aTest-Anything-Protocol consumer.
# Landing Strip
Alias:Landing
,landing
The Landing Strip reporter is a gimmicky test reporter simulating a plane landing 😃 unicode ftw
# List
Alias:List
,list
The List reporter outputs a simple specifications list as test cases pass or fail, outputting the failure details at the bottom of the output.
# Progress
Alias:Progress
,progress
The Progress reporter implements a simple progress-bar:
# JSON
Alias:JSON
,json
The JSON reporter outputs a single large JSON object when the tests have completed (failures or not).
By default, it will output to the console. To write directly to a file, use--reporter-option output=filename.json
.
# JSON Stream
Alias:JSONStream
,json-stream
The JSON Stream reporter outputs newline-delimited JSON “events” as they occur, beginning with a “start” event, followed by test passes or failures, and then the final “end” event.
# Min
Alias:Min
,min
The Min reporter displays the summary only, while still outputting errors on failure. This reporter works great with--watch
as it clears the terminal in order to keep your test summary at the top.
# Doc
Alias:Doc
,doc
The Doc reporter outputs a hierarchical HTML body representation of your tests. Wrap it with a header, footer, and some styling, then you have some fantastic documentation!
For example, suppose you have the following #"suite"><h1>Array</h1><dl><sectionclass="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>
The SuperAgent request librarytest documentation was generated with Mocha’s doc reporter using this Bash command:
$ mocha--reporter=doc|cat docs/head.html - docs/tail.html> docs/test.html
View SuperAgent’sMakefile for reference.
# Markdown
Alias:Markdown
,markdown
The Markdown reporter generates a markdown TOC and body for your test suite.This is great if you want to use the tests as documentation within a Githubwiki page, or a markdown file in the repository that Github can render. Forexample, here is the Connecttest output.
# XUnit
Alias:XUnit
,xunit
The XUnit reporter is also available. It outputs an XUnit-compatible XML document, often applicable in CI servers.
By default, it will output to the console. To write directly to a file, use--reporter-option output=filename.xml
.
To specify custom report title, use--reporter-option suiteName="Custom name"
.
# Third-Party Reporters
Mocha allows you to define custom reporters. For more information see thewiki.
Examples:
# HTML Reporter
Alias:HTML
,html
The HTML reporter is not intended for use on the command-line.
# Node.JS native ESM support
New in v7.1.0
Mocha supports writing your tests as ES modules, and not just using CommonJS. For example:
// test.mjsimport{add}from'./add.mjs';import assertfrom'assert';it('should add to numbers from an es module',()=>{ assert.equal(add(3,5),8);});
To enable this you don’t need to do anything special. Write your test file as an ES module. In Node.jsthis means either ending the file with a.mjs
extension, or, if you want to use the regular.js
extension, byadding"type": "module"
to yourpackage.json
.More information can be found in theNode.js documentation.
# Current Limitations
- Watch mode does not support ES Module test files
- Custom reporters andcustom interfacescan 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
orrewire
,hold off on using ES modules for your test files. You can switch to usingtestdouble
,which does support ESM.
# Running Mocha in the Browser
Mocha runs in the browser. Every release of Mocha will have new builds of./mocha.js
and./mocha.css
for use in the browser.
A typical setup might look something like the following, where we callmocha.setup('bdd')
to use theBDD interface before loading the test scripts, running themonload
withmocha.run()
.
<!DOCTYPEhtml><htmllang="en"><head><metacharset="utf-8"/><title>Mocha Tests</title><metaname="viewport"content="width=device-width, initial-scale=1.0"/><linkrel="stylesheet"href="https://unpkg.com/mocha/mocha.css"/></head><body><divid="mocha"></div><scriptsrc="https://unpkg.com/chai@4/chai.js"></script><scriptsrc="https://unpkg.com/mocha/mocha.js"></script><scriptclass="mocha-init"> mocha.setup('bdd'); mocha.checkLeaks();</script><scriptsrc="test.array.js"></script><scriptsrc="test.object.js"></script><scriptsrc="test.xhr.js"></script><scriptclass="mocha-exec"> mocha.run();</script></body></html>
# Grep
The browser may use the--grep
as functionality. Append a query-string to your URL:?grep=api
.
# Browser Configuration
Mocha options can be set viamocha.setup()
. Examples:
// 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:3,rootHooks:{beforeEach(done){...done();}},slow:'100',timeout:'2000',ui:'bdd'});
# Browser-specific Option(s)
Browser Mocha supports many, but not allcli options.To use acli option that contains a “-”, please convert the option to camel-case, (eg.check-leaks
tocheckLeaks
).
# Options that differ slightly fromcli options:
reporter
{string|constructor}You can pass a reporter’s name or a custom reporter’s constructor. You can findrecommended reporters for the browserhere. It is possible to usebuilt-in reporters as well. Their employment in browsers is neither recommended nor supported, open the console to see the test results.
# Options thatonly function in browser context:
noHighlighting
{boolean}If set totrue
, do not attempt to use syntax highlighting on output test code.
# Reporting
The HTML reporter is the default reporter when running Mocha in the browser. It looks like this:
Mochawesome is a great alternative to the default HTML reporter.
# Configuring Mocha (Node.js)
New in v6.0.0
Mocha supports configuration files, typical of modern command-line tools, in several formats:
- JavaScript: Create a
.mocharc.js
(or.mocharc.cjs
when using"type"="module"
in yourpackage.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’spackage.json
.
# Custom Locations
You can specify a custom location for your configuration file with the--config <path>
option. Mocha will use the file’s extension to determine how to parse the file, and will assume JSON if unknown.
You can specify a custompackage.json
location as well, using the--package <path>
option.
# Ignoring Config Files
To skip looking for config files, use--no-config
. Likewise, use--no-package
to stop Mocha from looking for configuration in apackage.json
.
# Priorities
If no custom path was given, and if there are multiple configuration files in the same directory, Mocha will search for — and use — only one. The priority is:
.mocharc.js
.mocharc.yaml
.mocharc.yml
.mocharc.jsonc
.mocharc.json
# Environment Variables
TheMOCHA_OPTIONS
environment variable may be used to specify command line arguments. These arguments take priority over those found in configuration files.
For example, setting thebail
andretries
options:
$MOCHA_OPTIONS="--bail --retries 3" mocha
# Merging
Mocha will alsomerge any options found inpackage.json
into its run-time configuration. In case of conflict, the priority is:
- Arguments specified on command-line
- Arguments specified in
MOCHA_OPTIONS
environment variable. - Configuration file (
.mocharc.js
,.mocharc.yml
, etc.) mocha
property ofpackage.json
Options which can safely be repeated (e.g.,--require
) will beconcatenated, with higher-priority configuration sources appearing earlier in the list. For example, a.mocharc.json
containing"require": "bar"
, coupled with execution ofmocha --require foo
, would cause Mocha to requirefoo
, thenbar
, in that order.
# Extending Configuration
Configurations can inherit from other modules using theextends
keyword. Seehere for more information.
# 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 ofreporter
. - Test files can be specified using
spec
, e.g.,"spec": "test/**/*.spec.js"
. - Flags to
node
arealso supported in configuration files. Use caution, as these can vary between versions of Node.js!
For more configuration examples, see theexample/config
directory on GitHub.
# Thetest/
Directory
By default,mocha
looks for the glob"./test/*.{js,cjs,mjs}"
, so you may want to putyour tests intest/
folder. If you want to include subdirectories, pass the--recursive
option.
To configure wheremocha
looks for tests, you may pass your own glob:
$ mocha--recursive"./spec/*.js"
Some shells support recursive matching by using the globstar (**
) wildcard. Bash >= 4.3 supports this with theglobstar
option whichmust be enabled to get the same results as passing the--recursive
option (ZSH andFish support this by default). With recursive matching enabled, the following is the same as passing--recursive
:
$ mocha"./spec/**/*.js"
You shouldalways quote your globs in npm scripts. If youuse quotes, thenode-glob
module willhandle its expansion. For maximum compatibility,surround the entire expression with double quotes and refrainfrom$
,"
,^
, and\
within your expression.
See thistutorial on using globs.
Note: Double quotes around the glob are recommended for portability.
# Error Codes
New in v6.0.0
When Mocha itself throws exception, the associatedError
will have acode
property. Where applicable, consumers should check thecode
property instead of string-matching against themessage
property. The following table describes these error codes:
Code | Description |
---|---|
ERR_MOCHA_INVALID_ARG_TYPE | wrong type was passed for a given argument |
ERR_MOCHA_INVALID_ARG_VALUE | invalid or unsupported value was passed for a given argument |
ERR_MOCHA_INVALID_EXCEPTION | a falsy or otherwise underspecified exception was thrown |
ERR_MOCHA_INVALID_INTERFACE | interface specified in options not found |
ERR_MOCHA_INVALID_REPORTER | reporter specified in options not found |
ERR_MOCHA_NO_FILES_MATCH_PATTERN | test file(s) could not be found |
ERR_MOCHA_UNSUPPORTED | requested behavior, option, or parameter is unsupported |
# Editor Plugins
The following editor-related packages are available:
# TextMate
TheMocha TextMate bundle includes snippets to make writing tests quicker and more enjoyable.
# JetBrains
JetBrains provides aNodeJS plugin for its suite of IDEs (IntelliJ IDEA, WebStorm, etc.), which contains a Mocha test runner, among other things.
The plugin is titledNodeJS, and can be installed viaPreferences >Plugins, assuming your license allows it.
# Wallaby.js
Wallaby.js is a continuous testing tool that enables real-time code coverage for Mocha with any assertion library in VS Code, Atom, JetBrains IDEs (IntelliJ IDEA, WebStorm, etc.), Sublime Text and Visual Studio for both browser and node.js projects.
# Emacs
Emacs support for running Mocha tests is available via a 3rd party packagemocha.el. The package is available on MELPA, and can be installed viaM-x package-install mocha
.
# Mocha Sidebar (VS Code)
Mocha sidebar is the most complete mocha extension for 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
Real live example code:
# Testing Mocha
To run Mocha’s tests, you will need GNU Make or compatible; Cygwin should work.
$cd /path/to/mocha$npminstall$npmtest
# More Information
In addition to chatting with us onour Discord, for additional information such as usingspies, mocking, and shared behaviours be sure to check out theMocha Wiki on GitHub.For a running example of Mocha, viewexample/tests.html. For the JavaScript API, view theAPI documentationor thesource.