ava, jasmine, jest, and mocha are core testing tools used to verify JavaScript code behavior, but they serve different roles in the ecosystem. jest is a complete platform built by Meta, offering built-in assertions, mocking, and snapshot testing with minimal setup. mocha is a flexible test runner that pairs with external libraries for assertions and mocking, giving developers full control over their stack. ava focuses on speed and simplicity, running tests concurrently by default with explicit async handling. jasmine is a standalone behavior-driven framework that requires no external dependencies, often found in legacy Angular projects or simple setups.
ava, jasmine, jest, and mocha are all designed to verify JavaScript code, but they handle test execution, assertions, and setup in very different ways. Let's break down how they tackle common engineering problems so you can pick the right tool for your stack.
jest uses test or it blocks with a global expect function.
beforeEach or beforeAll.// jest: Basic test structure
test('adds 1 + 2 to equal 3', () => {
expect(1 + 2).toBe(3);
});
mocha uses describe and it blocks but lacks built-in assertions.
assert or chai.describe.// mocha: Basic test structure
const assert = require('assert');
describe('Math', () => {
it('adds 1 + 2 to equal 3', () => {
assert.equal(1 + 2, 3);
});
});
ava uses test blocks where the assertion object t is passed in.
// ava: Basic test structure
import test from 'ava';
test('adds 1 + 2 to equal 3', t => {
t.is(1 + 2, 3);
});
jasmine uses describe and it with built-in expect.
// jasmine: Basic test structure
describe('Math', () => {
it('adds 1 + 2 to equal 3', () => {
expect(1 + 2).toBe(3);
});
});
jest provides a rich expect API built into the core.
toBe, toEqual, toContain.// jest: Assertions
expect(user.name).toBe('Alice');
expect(items).toContain('item1');
mocha relies on external libraries for assertions.
assert is common for simple checks.chai adds chainable language like Jest.// mocha: Assertions (using Node assert)
const assert = require('assert');
assert.strictEqual(user.name, 'Alice');
ava uses assertions attached to the t context object.
t.is, t.deepEqual, t.true.// ava: Assertions
t.is(user.name, 'Alice');
t.true(items.includes('item1'));
jasmine includes a built-in expect similar to Jest.
toBe, toEqual, toHaveBeenCalled.// jasmine: Assertions
expect(user.name).toBe('Alice');
expect(items).toContain('item1');
jest handles promises and async functions automatically.
async/await.done callback for older patterns.// jest: Async test
test('fetches data', async () => {
const data = await fetchData();
expect(data).toBeDefined();
});
mocha supports promises, async functions, or done callbacks.
done().// mocha: Async test
it('fetches data', async () => {
const data = await fetchData();
assert.ok(data);
});
ava treats any returned promise as an async test.
t.plan() if you need to assert a specific count.// ava: Async test
test('fetches data', async t => {
const data = await fetchData();
t.truthy(data);
});
jasmine supports async/await and promises natively.
done callback for compatibility.// jasmine: Async test
it('fetches data', async () => {
const data = await fetchData();
expect(data).toBeDefined();
});
jest has a powerful mocking system built in.
jest.fn() for functions and jest.mock() for modules.// jest: Mocking
const mockFn = jest.fn();
mockFn('hello');
expect(mockFn).toHaveBeenCalledWith('hello');
mocha does not include mocking; you need a library like Sinon.
sinon.stub() or sinon.spy().// mocha: Mocking (with Sinon)
const sinon = require('sinon');
const stub = sinon.stub(module, 'func');
ava does not include mocking; pairs well with Sinon or Test Double.
// ava: Mocking (with Sinon)
import sinon from 'sinon';
const stub = sinon.stub(module, 'func');
jasmine includes built-in spying and mocking capabilities.
spyOn() for existing methods or createSpy().// jasmine: Mocking
spyOn(object, 'method');
object.method();
expect(object.method).toHaveBeenCalled();
jest supports snapshot testing out of the box.
toMatchSnapshot() to save UI output.// jest: Snapshots
expect(component).toMatchSnapshot();
mocha requires a plugin for snapshot testing.
// mocha: Snapshots (with plugin)
// Requires jest-snapshot or similar plugin
expect(value).toMatchSnapshot();
ava requires a plugin for snapshot testing.
ava-plugin-snapshot to enable features.// ava: Snapshots (with plugin)
// Requires configuration and plugin
t.snapshot(value);
jasmine requires a plugin for snapshot testing.
jasmine-snapshot-reporter.// jasmine: Snapshots (with plugin)
// Requires external reporter or plugin
expect(value).toMatchSnapshot();
jest runs tests in parallel by default using workers.
// jest: Config (jest.config.js)
module.exports = {
workers: 4 // Runs tests in parallel
};
mocha runs tests serially by default.
// mocha: Config (.mocharc.json)
{
"parallel": false // Default is serial
}
ava runs tests concurrently by default in isolated processes.
// ava: Config (ava.config.js)
export default {
concurrency: 5 // Runs tests concurrently
};
jasmine runs tests serially by default.
// jasmine: Config (jasmine.json)
{
"random": true // Order can be random, but execution is serial
}
While the differences are clear, all four tools share core testing concepts.
describe or test to group logic.beforeEach and afterEach hooks.// Shared hook usage
beforeEach(() => {
// Reset state before each test
});
async/await.done patterns for legacy code.// Shared async pattern
it('works', async () => {
await doWork();
});
// Shared CI output
// โ adds 1 + 2 to equal 3
// โ fails when input is null
// Shared ignore pattern
// testPathIgnorePatterns: ['/node_modules/']
| Feature | Shared by All Four |
|---|---|
| Core Structure | ๐งช Describe/It blocks |
| Async | ๐ Promises & Async/Await |
| Hooks | ๐ BeforeEach/AfterEach |
| CI Ready | โ Terminal output & Exit codes |
| Config | ๐ ๏ธ Customizable via files |
| Feature | jest | mocha | ava | jasmine |
|---|---|---|---|---|
| Assertions | โ
Built-in expect | โ Needs chai or assert | โ
Built-in t.is | โ
Built-in expect |
| Mocking | โ
Built-in jest.fn | โ Needs sinon | โ Needs sinon | โ
Built-in spyOn |
| Snapshots | โ Built-in | โ Needs plugin | โ Needs plugin | โ Needs plugin |
| Concurrency | โก Parallel (workers) | ๐ข Serial (default) | โก Concurrent (isolated) | ๐ข Serial (default) |
| Setup | ๐ Batteries included | ๐งฉ Flexible stack | ๐ Fast & minimal | ๐ฆ Standalone |
jest is like a fully stocked workshop ๐จโit gives you everything you need immediately. Ideal for React, Vue, or general frontend projects where speed of setup and rich features matter most.
mocha is like a custom build kit ๐ ๏ธโperfect for teams who want to choose their own tools for assertions and mocking. Shines in complex Node.js backends where flexibility is key.
ava is like a speed-focused engine ๐๏ธโgreat for projects where test execution time is a bottleneck and isolation is critical. Best for teams willing to write explicit async code for better reliability.
jasmine is like a reliable classic car ๐โstill functional and standalone, but less common in new modern frontend stacks. Suitable for legacy Angular apps or simple scripts where adding heavy deps is not an option.
Final Thought: For most modern frontend teams, jest offers the best balance of features and ease of use. However, if you need specific control over your testing stack or maximum speed, mocha and ava remain strong choices.
Choose ava if you want fast test execution through concurrent runs and prefer a minimal configuration setup. It is ideal for projects where test isolation is critical and you want explicit control over async flows without hidden magic. This tool works well for teams that value speed and simplicity over a large plugin ecosystem.
Choose jasmine if you need a standalone framework with no external dependencies for assertions or mocking. It is suitable for legacy Angular projects or simple environments where adding a heavy tool like Jest is unnecessary. However, for modern React or Vue projects, other tools often provide better developer experience and community support.
Choose jest if you want a batteries-included solution that works out of the box with React, Vue, or Node.js projects. It is the best fit for teams that need built-in snapshot testing, code coverage, and mocking without configuring multiple libraries. This framework is widely adopted and offers the smoothest experience for most frontend architectures.
Choose mocha if you prefer to pick and choose your own assertion and mocking libraries rather than using built-in defaults. It is ideal for complex Node.js backends or projects requiring highly custom reporting and test organization. This runner offers maximum flexibility but requires more initial setup than integrated solutions.
Please support our friend Vadim Demedes and the people in Ukraine.

AVA is a test runner for Node.js with a concise API, detailed error output, embrace of new language features and thread isolation that lets you develop with confidence ๐
Watch this repository and follow the Discussions for updates.
Read our contributing guide if you're looking to contribute (issues / PRs / etc).

Translations: Espaรฑol, Franรงais, Italiano, ๆฅๆฌ่ช, ํ๊ตญ์ด, Portuguรชs, ะ ัััะบะธะน, ็ฎไฝไธญๆ
To install and set up AVA, run:
npm init ava
Your package.json will then look like this (exact version notwithstanding):
{
"name": "awesome-package",
"type": "module",
"scripts": {
"test": "ava"
},
"devDependencies": {
"ava": "^5.0.0"
}
}
Or if you prefer using Yarn:
yarn add ava --dev
Alternatively you can install ava manually:
npm install --save-dev ava
Make sure to install AVA locally. AVA cannot be run globally.
Don't forget to configure the test script in your package.json as per above.
Create a file named test.js in the project root directory.
Note that AVA's documentation assumes you're using ES modules.
import test from 'ava';
test('foo', t => {
t.pass();
});
test('bar', async t => {
const bar = Promise.resolve('bar');
t.is(await bar, 'bar');
});
npm test
Or with npx:
npx ava
Run with the --watch flag to enable AVA's watch mode:
npx ava --watch
AVA supports the latest release of any major version that is supported by Node.js itself. Read more in our support statement.
AVA adds code excerpts and clean diffs for actual and expected values. If values in the assertion are objects or arrays, only a diff is displayed, to remove the noise and focus on the problem. The diff is syntax-highlighted too! If you are comparing strings, both single and multi line, AVA displays a different kind of output, highlighting the added or missing characters.

AVA automatically removes unrelated lines in stack traces, allowing you to find the source of an error much faster, as seen above.
AVA automatically detects whether your CI environment supports parallel builds. Each build will run a subset of all test files, while still making sure all tests get executed. See the ci-parallel-vars package for a list of supported CI environments.
Please see the files in the docs directory:
We have a growing list of common pitfalls you may experience while using AVA. If you encounter any issues you think are common, comment in this issue.
t.plan()AVA, not Ava or ava. Pronounced /หeษชvษ/: Ay (face, made) V (vie, have) A (comma, ago)
It's the Andromeda galaxy.
Concurrency is not parallelism. It enables parallelism.
![]() | ![]() |
|---|---|
| Mark Wubben | Sindre Sorhus |