Framework
mochajs/mocha avatar
mochajs/mocha

Mocha: a test framework for Node.js and the browser

☕️ Classic, reliable, trusted test framework for Node.js and the browser

22,891 stars3,157 forksJavaScriptMIT

At a glance

What is it?
Mocha is a volunteer-maintained JavaScript test framework that runs in Node.js and in the browser. It gives you the test runner and the reporting layer, and leaves assertions, mocking and coverage to whichever libraries you pick.
Who is it for?
Mocha fits teams that want the runner separated from the assertion library, and that need the same specs to execute under Node.js and in a real browser. It is the wrong pick if you expect the framework to ship assertions, mocking and coverage in one install.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Mocha actually takes off your plate

Mocha is the runner, not the whole testing stack. It discovers test files, executes them in a defined order, applies hooks before and after each test or suite, and reports the result. Assertions are somebody else's job: the package keywords list chai alongside jest, ava, tape and jasmine, and the docs point you at an assertion library of your choosing. That split is the reason the project has stayed usable for so long. You can swap chai for Node's built-in assert without touching the runner, and you can change the reporter without touching a single spec.

The audience is narrower than the download numbers suggest. If you are testing a small Express service and you want one dependency that gives you assertions, spies and a coverage report, Mocha asks you to assemble three packages where a framework like Jest gives you one. Mocha pays off when the assembly is the point: a browser matrix, a custom reporter that emits your CI's format, or a suite that has to run under both Node.js and a headless browser from the same source files.

The README describes Mocha as an independent open-source project maintained exclusively by volunteers, and it points contributors at the maintainer's handbook and a list of good first issues. That is a governance statement as much as a support statement. There is no company behind the runner, so the pace of change depends on who shows up.

Suites, hooks and the runner loop

The model is BDD by default. describe() groups specs into a suite, it() declares a single test, and beforeEach, afterEach, before and after attach setup and teardown at the suite level. The topics list on the repository includes both bdd and tdd, so the TDD interface is a supported alternative rather than an afterthought. Hooks are where most of the practical design work happens: a beforeEach that opens a database connection runs once per test, not once per file, and the difference shows up as soon as a suite grows.

The runner walks the tree it built from those calls and reports through a pluggable reporter. The repository keeps mocha.css at the top level, which is the stylesheet for the HTML reporter, and browser-entry.js is the entry point used when the framework is bundled for browser execution. The package exposes two entry points that matter for consumers: main points at ./index.js and the bin map registers the mocha command at ./bin/mocha.js. The package is declared as type: module, and mocha.mjs sits at the top level for the ESM path.

That architecture is why Mocha composes well and why it feels sparse. Nothing in the loop assumes an assertion style, a mocking approach or a module system. You supply all three. The trade-off is real: a suite written against Mocha is portable but not self-contained, and a new contributor has to read the repository's own configuration before they can run anything.

Installing Mocha and running a first spec

Mocha is published on npm as mocha, and the README links the npm package page as the primary distribution channel. The engines field in package.json requires Node ^20.19.0 or >=22.12.0, so check your runtime before installing. The package registers its command-line entry in the bin map, which is what makes the local mocha binary available to npm scripts:

json
{
  "bin": {
    "mocha": "./bin/mocha.js"
  }
}

That is the exact bin declaration from package.json. Once the package is installed as a dependency, the mocha command resolves to ./bin/mocha.js, and the repository's own scripts invoke tooling the same way. The default entry for consumers is main, which points at ./index.js; the package is declared as type: module, with mocha.mjs at the top level for the ESM path.

Configuration lives in .mocharc.yml at the repository root, and the example directory contains a config subdirectory with sample configuration. If you need to point the runner somewhere other than the default test directory, set it in .mocharc.yml rather than passing flags on every invocation. The README does not document a rollback command for a failed Mocha upgrade, so pin the version in package.json if you need a predictable downgrade path.

Where Mocha is the wrong tool

Mocha has no assertion library, no mocking library and no built-in coverage instrumentation. The .nycrc file at the top level is a reminder that coverage in this ecosystem is a separate tool layered on top of the runner, not a feature of it. If your team wants one command that produces a pass or fail plus a coverage percentage with no additional configuration, Mocha will feel like extra work at every step.

Snapshots are the other gap. Nothing in the repository layout or the README describes a snapshot facility, so if your suite leans on serialized output comparison you are looking at a different framework or a plugin you have to evaluate yourself. Similarly, the README does not describe a watch-mode workflow in the text available, so do not assume interactive re-run behaviour without checking the documentation site.

The maintenance model is the second constraint. The README states the project is maintained exclusively by volunteers, and it asks companies that use Mocha to consider sponsoring so maintainers can dedicate time to maintenance and new features. That is honest, and it also means issue response times are not a service level. Teams with a compliance requirement for vendor-backed support will not find it here.

Mocha against Jest, on the axis that matters

Jest is the obvious comparison and the package keywords list it directly. The difference is where the batteries live. Jest bundles the runner, the assertion library, mocking and snapshot testing into one dependency and one configuration file. Mocha bundles the runner and the reporter and stops there. Adopting Jest is a decision about a stack; adopting Mocha is a decision about a runner and then a series of smaller decisions about everything else.

That shows up in migration cost in both directions. Moving a Jest suite to Mocha means replacing the expect assertions, replacing the mock helpers, and finding a substitute for snapshots. Moving a Mocha suite to Jest means the reverse, plus reconciling the hook semantics. If your suite is mostly plain assertions over pure functions, that migration is mechanical. If it leans on snapshots and module mocking, it is not.

The second comparison worth making is against Node's own test runner, which is built in and needs no dependency at all. The case for Mocha over a built-in runner is the browser story. The repository carries a browser-entry.js, a playwright.config.js and a test-browser:playwright script, and the topics list includes browser alongside node. Running the same spec files in a real browser is a capability Mocha has supported for years and that a Node-only runner cannot match.

Licence, maintenance and the cost of an upgrade

Mocha is licensed MIT, with the copyright line reading 2011-2026 OpenJS Foundation and contributors. MIT is permissive: it allows commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is a description of the licence text, not legal advice, and any organisation with a licence review process should run the LICENSE file through it.

The maintenance cost sits on the consumer side. Mocha is a test-time dependency, so it never ships to production, but a major version bump can still break your suite. The release history shows v12.0.0 on 2026-08-31, v12.0.1 on 2026-09-11 and v12.0.2 on 2026-09-17, which is a fast patch cadence after a major. The CHANGELOG.md at the repository root is where the breaking changes for v12.0.0 are recorded, and it is the file to read before upgrading rather than after.

The runtime constraint is the other recurring cost. The engines field requires Node ^20.19.0 or >=22.12.0, so a team on an older LTS line has to move Node before it can move Mocha. The repository also carries an installed-check script with an engine check, which suggests the project validates its own engine claims in CI. Budget for the Node upgrade, not just the Mocha upgrade.

Editorial conclusion

Mocha fits teams that want the runner separated from the assertion library, and that need the same specs to execute under Node.js and in a real browser. It is the wrong pick if you expect the framework to ship assertions, mocking and coverage in one install. Before adopting it, confirm that your Node version satisfies the engines field (^20.19.0 or >=22.12.0), check that your assertion library supports ESM, and read the v12.0.0 entry in CHANGELOG.md for breaking changes. The last push to the repository was on 2026-09-19.

Frequently asked questions

How do I install Mocha in a Node.js project?

Install it from npm as a development dependency, then run the local mocha binary through your package scripts. The engines field requires Node ^20.19.0 or >=22.12.0.

How do I use Mocha to run a test file?

Put your spec files in a test directory and run the mocha command; the default glob picks them up. Suites are declared with describe, individual tests with it, and hooks such as beforeEach attach setup at the suite level.

Does Mocha include an assertion library?

No. Mocha is the runner and the reporter; assertions come from a library you choose, such as chai, or from Node's built-in assert module. The package keywords list chai, jest, ava, tape and jasmine as neighbouring tools rather than bundled ones.

Can Mocha run tests in a browser as well as in Node.js?

Yes. The repository includes browser-entry.js, a playwright.config.js and a test-browser:playwright script, and the topics list browser alongside node. The same spec files can be executed in a browser through the browser entry point.

Official sources

  1. License: MIT
  2. mochajs/mocha on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mochajs-mocha.svg)](https://hysenlabs.com/projects/mochajs-mocha)