Mocha v6 adds Configuration File Support & Drops Node.js v4.x

The next major release of Mocha, v6.0.0, will be released "in the near future."   Since it contains significant changes to command-line flags and configuration, we're being cautious and plan on publishing one or more prerelease versions.

Any prerelease versions will be installable via npm install mocha@next.

Notably, given Mocha's commitment to only supporting maintained versions of Node.js, Mocha v6.0.0 will drop support for Node.js v4.x.

But the big story is configuration file support!  Let's start with a little history.

mocha.opts

The need for configuration was recognized early in Mocha's history.  

Before v6, the way you'd "configure" Mocha for command-line use would be to create a mocha.opts file.  This file would contain actual command-line flags which would be essentially grafted on to Node.js' process.argv Array.  These flags would then be combined with any user-supplied command-line arguments, then passed to the secondary _mocha executable.   This is how Mocha is able to provide "direct" support for Node.js flags--by invoking a child node process.

I'd call this method of "configuring" a command-line app "unusual" at best; no effort was made to intelligently reconcile mocha.opts with user-supplied  arguments.  It was easy to encounter conflicts or other bad weirdness when using mocha.opts.

Several years ago, we knew that Mocha needed actual honest-to-goodness configuration files.  A lack of maintenance resources meant it just wasn't a high priority.

Meanwhile, technical debt kept accumulating around Mocha's command-line option parsing.  Coupled with new features in Node.js (e.g., process.allowedNodeEnvironmentFlags), it became pragmatic to refactor this system.  

Option Parrrsing

With v6, Mocha adopts the powerful yargs for argument parsing.  It offers features and control that Mocha had been missing, and ultimately provides not just a better developer experience, but a better experience for the user of Mocha.

yargs just so happens to support configuration ("RC") files and loading of options via package.json out-of-the-box.  Since we were already shredding the option-parsing code, this refactor became a great opportunity to tackle Mocha's "configuration" problem.

Even if it was a great opportunity, it was still more work than anticipated!  This article is not a post-mortem, however.  In the end, it was worth the effort, and I think Mocha's users will appreciate it.

With the help of yargs, Mocha v6 supports configuration via JS, JSON, or YAML RC file, package.json and mocha.opts.  

Introducing .mocharc.whatever

Instead of (or in addition to, if you please) mocha.opts, Node.js users of Mocha can now create a .mocharc.js, .mocharc.json, .mocharc.yml/yaml, or add a mocha property to a package.json.  This is the same kind of thing that, say, ESLint supports (though not identical).

Here's an example mocharc.yaml containing Mocha's defaults:

diff: true
extension:
  - js
opts: ./test/mocha.opts
package: ./package.json
reporter: spec
slow: 75
timeout: 2000
ui: bdd

This can be JSON instead:

{
  "diff": true,
  "extension": ["js"],
  "opts": "./test/mocha.opts",
  "package": "./package.json",
  "reporter": "spec",
  "slow": 75,
  "timeout": 2000,
  "ui": "bdd"
}

If you please, that same JSON could be in the mocha property of your package.json.  If you need some special logic, here's the same in JavaScript:

module.exports = {
  diff: true,
  extension: ['js'],
  opts: './test/mocha.opts',
  package: './package.json',
  reporter: 'spec',
  slow: 75,
  timeout: 2000,
  ui: 'bdd'
};

Each option name corresponds to a command-line option as listed in mocha --help (which has also been overhauled).

Things to Know about Options

  1. On the command-line, any boolean flag can be negated by prepending --no- to the flag.  For example, --no-diff will disable diffs.  This is appropriate for mocha.opts.  But in a configuration file, you should use diff: false or its equivalent.  You could use no-diff: true, but that's silly, right?
  2. Any option of type array (use mocha --help to see these) can be specified multiple times.  These will be concatenated, so a require: esm in your .mocharc.yml and a --require my-thing on the command-line will result in "require": ["my-thing, "esm"].  Command-line arguments will be shifted on to the array.
  3. Mocha loads config using the following priority: command-line args first, RC file second, package.json third, mocha.opts fourth, and then finally Mocha's own defaults.
  4. To specify a test file or directory in an options file, use the spec option.  If you care about order, use file instead.
  5. Aliases are allowed in config files; see these in Mocha's "help" output.
  6. When run via mocha, Node.js and V8 flags are also supported in configuration files and package.json (mocha.optsalready did this).
  7. Any V8 flag can be supplied by prepending --v8- to the flag name.  For example, if you wanted --randomize-hashes, that'd be --v8-randomize-hashes on the command line, or v8-randomize-hashes: true in a YAML config.  Only supported when running Mocha via mocha.
  8. Mocha only supports the flags your current version of node supports.  Again, only supported when running Mocha via mocha.
  9. Unknown flags/options are ignored; --butts does nothing

Try It Out!

Some example config files are available in the repo, and our documentation (unfortunately) already reflects these changes.

When released--likely this week--I encourage you to check out the first prerelease of Mocha v6, which should be version 6.0.0-0, installable via npm i mocha@next.