8.3 KiB
Define tests with a Jest-like API imported from the built-in bun:test module. Long term, Bun aims for complete Jest compatibility; at the moment, a limited set of expect matchers are supported.
Basic usage
To define a simple test:
import { expect, test } from "bun:test";
test("2 + 2", () => {
expect(2 + 2).toBe(4);
});
{% details summary="Jest-style globals" %}
As in Jest, you can use describe, test, expect, and other functions without importing them. Unlike Jest, they are not injected into the global scope. Instead, the Bun transpiler will automatically inject an import from bun:test internally.
typeof globalThis.describe; // "undefined"
typeof describe; // "function"
This transpiler integration only occurs during bun test, and only for test files & preloaded scripts. In practice there's no significant difference to the end user.
{% /details %}
Tests can be grouped into suites with describe.
import { expect, test, describe } from "bun:test";
describe("arithmetic", () => {
test("2 + 2", () => {
expect(2 + 2).toBe(4);
});
test("2 * 2", () => {
expect(2 * 2).toBe(4);
});
});
Tests can be async.
import { expect, test } from "bun:test";
test("2 * 2", async () => {
const result = await Promise.resolve(2 * 2);
expect(result).toEqual(4);
});
Alternatively, use the done callback to signal completion. If you include the done callback as a parameter in your test definition, you must call it or the test will hang.
import { expect, test } from "bun:test";
test("2 * 2", done => {
Promise.resolve(2 * 2).then(result => {
expect(result).toEqual(4);
done();
});
});
Timeouts
Optionally specify a per-test timeout in milliseconds by passing a number as the third argument to test.
import { test } from "bun:test";
test("wat", async () => {
const data = await slowOperation();
expect(data).toBe(42);
}, 500); // test must run in <500ms
test.skip
Skip individual tests with test.skip. These tests will not be run.
import { expect, test } from "bun:test";
test.skip("wat", () => {
// TODO: fix this
expect(0.1 + 0.2).toEqual(0.3);
});
test.todo
Mark a test as a todo with test.todo. These tests will be run, and the test runner will expect them to fail. If they pass, you will be prompted to mark it as a regular test.
import { expect, test } from "bun:test";
test.todo("fix this", () => {
myTestFunction();
});
To exclusively run tests marked as todo, use bun test --todo.
$ bun test --todo
test.only
To run a particular test or suite of tests use test.only() or describe.only(). Once declared, running bun test --only will only execute tests/suites that have been marked with .only().
import { test, describe } from "bun:test";
test("test #1", () => {
// does not run
});
test.only("test #2", () => {
// runs
});
describe.only("only", () => {
test("test #3", () => {
// runs
});
});
The following command will only execute tests #2 and #3.
$ bun test --only
test.if
To run a test conditionally, use test.if(). The test will run if the condition is truthy. This is particularly useful for tests that should only run on specific architectures or operating systems.
test.if(Math.random() > 0.5)("runs half the time", () => {
// ...
});
const macOS = process.arch === "darwin";
test.if(macOS)("runs on macOS", () => {
// runs if macOS
});
To instead skip a test based on some condition, use test.skipIf() or describe.skipIf().
const macOS = process.arch === "darwin";
test.skipIf(macOS)("runs on non-macOS", () => {
// runs if *not* macOS
});
Matchers
Bun implements the following matchers. Full Jest compatibility is on the roadmap; track progress here.
{% table %}
- ✅
.not
- ✅
.toBe()
- ❌
.extend
- ✅
.any()
{% /table %}