---
title: Node.js Test Runner
description: Learn how to integrate Allure with the Node.js test runner to generate rich, interactive test reports. Follow step-by-step setup, test execution, and report generation guidance.
---

# Getting started with Allure Node.js Test Runner

[![Allure Node.js Test Runner npm latest version](https://img.shields.io/npm/v/allure-node-test?style=flat "Allure Node.js Test Runner npm latest version")](https://www.npmjs.com/package/allure-node-test)

Generate beautiful HTML reports using [Allure Report](https://allurereport.org/docs/) and your [Node.js test runner](https://nodejs.org/api/test.html) (`node:test`) tests.

## Setting up

### 1. Prepare your project

1. Make sure [Node.js](https://nodejs.org/) is installed.

   Full functionality, including the Runtime API with unchanged `node:test` imports, requires Node.js 26.1 or later. On older Node.js versions, starting with Node.js 20, the integration works in a reporter-only mode, see the [version note](#node-js-version-requirements) below.

1. Open a terminal and go to the project directory. For example:

   ```bash
   cd /home/user/myproject
   ```

1. Make sure Allure Report is installed. If it's not, follow the [installation instructions](/docs/v2/install/). Note that Allure Report requires Java.

1. Install the Allure Node.js Test Runner integration:

   **npm:**
   ```bash
   npm install --save-dev allure-node-test allure-js-commons
   ```

   **yarn:**
   ```bash
   yarn add --dev allure-node-test allure-js-commons
   ```

   **pnpm:**
   ```bash
   pnpm add -D allure-node-test allure-js-commons
   ```

   Keep `allure-node-test` and `allure-js-commons` on the same version.

   No configuration files are needed — the integration is activated entirely from the command line when you run the tests. Your test files themselves do not need any changes — keep using `node:test` as usual.

### 2. Run tests

Run your Node.js tests with the Allure reporter and the setup preload:

```bash
node --test --import allure-node-test/setup --test-reporter allure-node-test/reporter
```

The two command-line options play different roles:

- `--test-reporter allure-node-test/reporter` collects test events and writes the Allure result files. This is the only required part.
- `--import allure-node-test/setup` enables the Runtime API (`allure-js-commons` calls inside tests) and [test plan filtering](#select-tests-via-a-test-plan-file). Without it, Runtime API calls print a warning and have no effect on the report (the bodies of `step()` calls still run).

For convenience, add the commands as scripts to your `package.json`:

```json
{
  "scripts": {
    "test:allure": "node --test --import allure-node-test/setup --test-reporter allure-node-test/reporter"
  }
}
```

This will save the necessary data into `allure-results` or another directory, according to the [configuration](/docs/node-test-configuration/). If the directory already exists, new files will be added to the existing ones so that a future report will be based on them all.

#### Node.js version requirements

Warning:
The `allure-node-test/setup` preload requires Node.js 26.1 or later and fails fast with a descriptive error on older versions. On older Node.js versions (20 or later), run the reporter without the preload:

```bash
node --test --test-reporter allure-node-test/reporter
```

In this reporter-only mode, only the Runtime API and test plan filtering are unavailable. Everything else keeps working: test statuses, the [Metadata API](#writing-tests) (tags in test names), suite hierarchies, automatic output attachments, and all [configuration options](/docs/node-test-configuration/).

There is one exception: when the `ALLURE_TESTPLAN_PATH` environment variable points to a [test plan file](#select-tests-via-a-test-plan-file), the preload can be used even on Node.js versions older than 26.1. In that case, it only filters the test execution; Runtime API calls still require Node.js 26.1 or later.

#### Keeping the console output

When a custom test reporter is specified, Node.js no longer prints its default console output. To keep a console reporter alongside Allure, list several reporters and give each of them a destination:

```bash
node --test \
  --test-reporter spec --test-reporter-destination stdout \
  --test-reporter allure-node-test/reporter --test-reporter-destination stdout
```

The Allure reporter writes its data to the results directory and prints nothing, so its destination value has no visible effect — it is only required because Node.js expects one destination per reporter.

### 3. Generate a report

Finally, convert the test results into an HTML report. This can be done by one of two commands:

- `allure generate` processes the test results and saves an HTML report into the `allure-report` directory. To view the report, use the `allure open` command.

- `allure serve` creates the same report as `allure generate`, then automatically opens the main page of the report in a web browser.

## Writing tests

The Allure Node.js Test Runner integration extends the standard reporting features of the Node.js test runner by providing additional capabilities for crafting more informative and structured tests. This section highlights key enhancements that can be utilized:

- **Metadata Annotation**: Enhance test reports with [descriptions, links, and other metadata](#add-metadata).
- **Test Organization**: Structure your tests into clear hierarchies for better readability and organization, see [organize tests](#organize-tests).
- **Step Division**: Break down tests into smaller [test steps](#divide-a-test-into-steps) for easier understanding and maintenance.
- **Parametrized Tests**: Clearly describe the parameters for [parametrized tests](#describe-parametrized-tests) to specify different scenarios.
- **Set labels globally**: Use [environment variables](#set-labels-globally) to set metadata and other labels.
- **Attachments**: Capture [files and other content](#attach-files) during test execution.
- **Test Selection**: Use a test plan file to [select which tests to run](#select-tests-via-a-test-plan-file), allowing for flexible test execution.
- **Environment Details**: Include comprehensive [environment information](#environment-information) to accompany the test report.

In most cases, Allure Node.js Test Runner provides two different ways to use a feature: the Runtime API and the Metadata API.

- **Runtime API**: use Allure's functions to add certain data to the test result during its execution. This approach allows for constructing the data dynamically.

  Note that it is recommended to call Allure's functions as close to the beginning of the test as possible. This way, the data will be added even if the test fails early.

  The Runtime API requires running with `--import allure-node-test/setup` on Node.js 26.1 or later.

- **Metadata API**: add a metadata tag (beginning with `@`) into the test name. The integration will extract it and update the test result's data accordingly. When using this approach, the data is guaranteed to be added regardless of how the test itself runs. The Metadata API works on any supported Node.js version (20 or later), including the reporter-only mode.

Your test files keep their native imports — `allure-js-commons` is only used for the reporting functions:

```js
import { label, step } from "allure-js-commons";
import assert from "node:assert/strict";
import test from "node:test";

test("signing in", async () => {
  await label("severity", "critical");
  await step("submit form", async () => {});

  assert.equal(1 + 1, 2);
});
```

All the usual ways of organizing `node:test` tests are supported: `describe()` suites are mapped to Allure suite labels, and native `t.test()` subtests are reported as separate test results.

Other standard `node:test` features are reported as you would expect:

- Tests marked with `skip` or `todo` appear in the report as Skipped.
- If a native `before()`, `beforeEach()`, `afterEach()`, or `after()` hook fails, the failed hook is preserved in the report as a fixture attached to the affected tests, and the failure is also recorded as an error of the test run as a whole. Tests cancelled by a failed `before()` hook appear as Skipped, a failure in a `beforeEach()` or `afterEach()` hook is reported as the affected test's own status, and a failed `after()` hook changes the statuses of the tests in its suite only if the hook's failure is more severe than their own results.

### Add Metadata

Allure allows you to enrich your reports with a variety of [metadata](/docs/v2/readability/#description-links-and-other-metadata). This additional information provides context and details for each test, enhancing the report's usefulness. Refer to the [metadata reference section](/docs/node-test-reference/#metadata) for an exhaustive list of what can be added.

**Runtime API:**
```js
import * as allure from "allure-js-commons";
import test from "node:test";

test("Test Authentication", async () => {
  await allure.displayName("Test Authentication");
  await allure.owner("John Doe");
  await allure.tags("Web interface", "Authentication");
  await allure.severity("critical");
  // ...
});
```

**Metadata API:**
```js
import test from "node:test";

test(
  "Test Authentication" +
    " @allure.label.owner:JohnDoe" +
    " @allure.label.tag:WebInterface" +
    " @allure.label.tag:Authentication" +
    " @allure.label.severity:critical",
  async () => {
    // ...
  },
);
```

### Organize tests

As described in [Improving navigation in your test report](/docs/v2/navigation/), Allure supports multiple ways to organize tests into hierarchical structures.

To specify a test's location in the [behavior-based hierarchy](/docs/v2/navigation/#behavior-based-hierarchy):

**Runtime API:**
```js
import * as allure from "allure-js-commons";
import test from "node:test";

test("Test Authentication", async () => {
  await allure.epic("Web interface");
  await allure.feature("Essential features");
  await allure.story("Authentication");
  // ...
});
```

**Metadata API:**
```js
import test from "node:test";

test(
  "Test Authentication" +
    " @allure.label.epic:WebInterface" +
    " @allure.label.feature:EssentialFeatures" +
    " @allure.label.story:Authentication",
  async () => {
    // ...
  },
);
```

To specify a test's location in the [suite-based hierarchy](/docs/v2/navigation/#suite-based-hierarchy):

**Runtime API:**
```js
import * as allure from "allure-js-commons";
import test from "node:test";

test("Test Authentication", async () => {
  await allure.parentSuite("Tests for web interface");
  await allure.suite("Tests for essential features");
  await allure.subSuite("Tests for authentication");
  // ...
});
```

**Metadata API:**
```js
import test from "node:test";

test(
  "Test Authentication" +
    " @allure.label.parentSuite:TestsForWebInterface" +
    " @allure.label.suite:TestsForEssentialFeatures" +
    " @allure.label.subSuite:TestsForAuthentication",
  async () => {
    // ...
  },
);
```

By default, the suite hierarchy is built from the `describe()` blocks the test is nested in. For native `t.test()` subtests, the parent test's name is also used as a suite label. Suite labels set via the Runtime API or the Metadata API override the generated ones.

### Divide a test into steps

To [create steps and sub-steps](/docs/steps/), you can use the `step()` function, see the [reference](/docs/node-test-reference/#test-steps).

```js
import * as allure from "allure-js-commons";
import { Status } from "allure-js-commons";
import test from "node:test";

test("Test Authentication", async () => {
  await allure.step("Step 1", async () => {
    await allure.step("Sub-step 1", async (ctx) => {
      await ctx.parameter("foo", "1");
      // ...
    });
    await allure.step("Sub-step 2", async (ctx) => {
      await ctx.parameter("foo", "2");
      // ...
    });
  });
  await allure.logStep("Step 2", Status.SKIPPED);
});
```

### Describe parametrized tests

To implement the [parametrized tests](/docs/v2/readability/#parametrized-tests) pattern with the Node.js test runner, write the test inside a loop and use the variable parameters in both the title and the body. Each iteration is treated as a separate test run by Allure Report.

To display a parameter value in the test report, pass it to the [`parameter()`](/docs/node-test-reference/#parametrized-tests) function.

```js
import * as allure from "allure-js-commons";
import test from "node:test";

for (const login of ["johndoe", "johndoe@example.com"]) {
  test(`Test Authentication as ${login}`, async () => {
    await allure.parameter("login", login);
    await allure.parameter("time", new Date().toUTCString(), { excluded: true });
    // ...
  });
}
```

### Set labels globally

Any [labels](/docs/node-test-reference/#label), including custom ones, can be set via environment variables in your operating system. Here's an example:

**MacOS/Linux:**
```bash
export ALLURE_LABEL_epic=WebInterface
node --test --import allure-node-test/setup --test-reporter allure-node-test/reporter
```

**Windows:**
```powershell
$Env:ALLURE_LABEL_epic = "WebInterface"
node --test --import allure-node-test/setup --test-reporter allure-node-test/reporter
```

### Attach files

In Allure reports, you have the ability to [attach various types of files](/docs/attachments/), which can greatly enhance the comprehensibility of the report.

For detailed instructions on how to implement attachments, refer to the [attachments section in the Allure Node.js Test Runner reference](/docs/node-test-reference/#attachments).

```js
import * as allure from "allure-js-commons";
import { ContentType } from "allure-js-commons";
import test from "node:test";

test("Test Authentication", async () => {
  // ...

  await allure.attachment("Text file", "This is the file content.", ContentType.TEXT);

  await allure.attachmentPath("Screenshot", "/path/to/image.png", {
    contentType: ContentType.PNG,
    fileExtension: "png",
  });
});
```

Additionally, anything written to the standard output or the standard error stream during a test run is captured and added as text attachments named "stdout" and "stderr", and messages logged with the built-in `t.diagnostic()` are added as a text attachment named "diagnostics". These attachments are added to the test run as a whole rather than to individual tests, because Node.js does not currently include a test identifier in its output events.

### Select tests via a test plan file

If the `ALLURE_TESTPLAN_PATH` environment variable is defined and points to an existing file, only the tests listed in this file will be run.

Test plan filtering requires the `--import allure-node-test/setup` preload: it skips the tests outside the plan before their bodies execute, and those skips do not appear in the report. In reporter-only mode (without the preload), the test plan is not applied — if tests run, they are reported.

When `ALLURE_TESTPLAN_PATH` is set, the preload may be used even on Node.js versions older than 26.1: it then only filters test execution, while Runtime API calls still require Node.js 26.1 or later.

Here's an example of running tests according to a file named `testplan.json`:

**MacOS/Linux:**
```bash
export ALLURE_TESTPLAN_PATH=testplan.json
node --test --import allure-node-test/setup --test-reporter allure-node-test/reporter
```

**Windows:**
```powershell
$Env:ALLURE_TESTPLAN_PATH = "testplan.json"
node --test --import allure-node-test/setup --test-reporter allure-node-test/reporter
```

Note that native `t.test()` subtests only exist while their parent test is running, so they cannot be filtered individually. If a test plan selector points to a subtest, the parent test is run in full, and every test and subtest that actually runs is reported. For this to work, a test plan entry that points to a subtest must include a selector, not just an Allure ID.

### Environment information

For the main page of the report, you can collect various information about the environment in which the tests were executed. To do so, define the [`environmentInfo`](/docs/node-test-configuration/#environmentinfo) object in the configuration.

For example, it is a good idea to record the OS version and the Node.js version. This may help the future reader investigate bugs that are reproducible only in some environments.

**MacOS/Linux:**
```bash
export ALLURE_NODE_TEST_CONFIG='{"environmentInfo":{"os_platform":"linux","node_version":"26.1.0"}}'
node --test --import allure-node-test/setup --test-reporter allure-node-test/reporter
```

**Windows:**
```powershell
$Env:ALLURE_NODE_TEST_CONFIG = '{"environmentInfo":{"os_platform":"windows","node_version":"26.1.0"}}'
node --test --import allure-node-test/setup --test-reporter allure-node-test/reporter
```

