---
title: TestCafe
description: Learn how to integrate Allure with TestCafe tests to generate rich, interactive test reports. Follow step-by-step setup, test execution, and report generation guidance.
---

# Getting started with Allure TestCafe

[![Allure TestCafe npm latest version](https://img.shields.io/npm/v/testcafe-reporter-allure-official?style=flat "Allure TestCafe npm latest version")](https://www.npmjs.com/package/testcafe-reporter-allure-official)

Generate beautiful HTML reports using [Allure Report](https://allurereport.org/docs/) and your [TestCafe](https://testcafe.io/) tests.

## Setting up

### 1. Prepare your project

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

   The integration is tested against Node.js 18 and higher. Older versions may work, but we can't guarantee that.

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/v3/install/). Note that Allure Report requires Java.

   Alternatively, install Allure Report 3 as a local npm package:

   ```bash
   npm install --save-dev allure
   ```

1. Install the Allure TestCafe reporter and make sure that TestCafe itself is also listed in the project's dependencies.

   **npm:**
   ```bash
   npm install --save-dev testcafe testcafe-reporter-allure-official
   ```

   **yarn:**
   ```bash
   yarn add --dev testcafe testcafe-reporter-allure-official
   ```

   **pnpm:**
   ```bash
   pnpm add -D testcafe testcafe-reporter-allure-official
   ```

### 2. Configure the reporter

The recommended way to configure the reporter is with a JavaScript config file. This also enables [test plan filtering](#select-tests-via-a-test-plan-file), which is required for Allure's smart retry and agent-mode workflows.

Create a `.testcaferc.cjs` file at the root of your project:

```js
const { createAllureTestPlanFilter } = require("testcafe-reporter-allure-official/testplan");

module.exports = {
  src: ["tests/**/*.test.js"],
  browsers: ["chromium:headless"],
  reporter: ["spec", "allure-official"],
  filter: createAllureTestPlanFilter(),
};
```

The `createAllureTestPlanFilter()` call returns `undefined` when `ALLURE_TESTPLAN_PATH` is not set, so TestCafe runs normally in that case. It is safe to leave enabled permanently.

Info:
JSON config files (`.testcaferc.json`) cannot use function-based filters. For the recommended Allure setup, use `.testcaferc.js`, `.testcaferc.cjs`, or the [runner API](#runner-api).

If you only need the reporter without test plan support, you can use a JSON config:

```json
{
  "src": ["tests/**/*.test.js"],
  "browsers": ["chromium:headless"],
  "reporter": ["spec", "allure-official"]
}
```

Or pass the reporter name on the command line:

```bash
testcafe "chromium:headless" tests -r spec,allure-official
```

#### Runner API

Use the [TestCafe runner API](https://testcafe.io/documentation/402641/reference/testcafe-api/runner) when you need to set reporter options such as a custom output directory or link templates:

```js
const createTestCafe = require("testcafe");
const createAllureTestCafeReporter = require("testcafe-reporter-allure-official");
const { createAllureTestPlanFilter } = require("testcafe-reporter-allure-official/testplan");

(async () => {
  const testcafe = await createTestCafe();

  try {
    const runner = testcafe.createRunner();

    await runner
      .src(["tests/**/*.test.js"])
      .browsers(["chromium:headless"])
      .filter(createAllureTestPlanFilter())
      .reporter(
        createAllureTestCafeReporter({
          resultsDir: "./out/allure-results",
        }),
      )
      .run();
  } finally {
    await testcafe.close();
  }
})();
```

See [Configuration](/docs/testcafe-configuration/) for all available reporter options.

### 3. Run tests

Run your TestCafe tests the same way as you would run them usually. For example:

**npm:**
```bash
npx testcafe --config-file .testcaferc.cjs
```

**yarn:**
```bash
yarn testcafe --config-file .testcaferc.cjs
```

**pnpm:**
```bash
pnpm exec testcafe --config-file .testcaferc.cjs
```

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

### 4. 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

This section covers what the integration adds beyond standard TestCafe reporting:

- **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.
- **Hooks**: Use the runtime API inside [fixture and test hooks](#hooks) to add labels, steps, and attachments from setup and teardown code.
- **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**: Add [screenshots and other files](#attach-files) to the test report.
- **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.

Allure TestCafe provides three ways to assign metadata and annotations to tests:

- **Runtime API**: call Allure's functions from `allure-js-commons` during test execution to add data dynamically.

  It is recommended to call these functions as close to the beginning of the test as possible so the data is recorded even if the test fails early.

- **Meta API**: set TestCafe [fixture or test metadata](https://testcafe.io/documentation/403436/guides/intermediate-guides/metadata-and-filtering#define-test-metadata) using Allure-specific keys. This is the most robust approach: metadata is resolved before the test starts and is guaranteed to be present in the report.

- **Title annotations**: embed annotations directly in the test name using `@allure.<type>=<value>` syntax. These are extracted at test start time, before the test body runs.

### Add metadata

Add [descriptions, links, labels, and more](/docs/v3/readability/#description-links-and-other-metadata) to your test results. See the [reference](/docs/testcafe-reference/#metadata) for the complete list.

**Runtime API:**
```js
const { displayName, owner, tags, severity } = require("allure-js-commons");

fixture`Authentication`.page`https://example.com/login`;

test("sign in", async () => {
  await displayName("Sign in");
  await owner("alice");
  await tags("Web interface", "Authentication");
  await severity("critical");
  // ...
});
```

**Meta API:**
```js
fixture`Authentication`.page`https://example.com/login`.meta({
  "allure.label.tag": ["Web interface", "Authentication"],
});

test.meta({
  "allure.label.owner": "alice",
  "allure.label.severity": "critical",
})("sign in", async (t) => {
  // ...
});
```

**Title annotations:**
```js
fixture`Authentication`.page`https://example.com/login`;

test(
  "sign in" +
    " @allure.label.owner=alice" +
    " @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/v3/navigation/), Allure supports multiple ways to organize tests into hierarchical structures.

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

**Runtime API:**
```js
const { epic, feature, story } = require("allure-js-commons");

fixture`Authentication`.page`https://example.com/login`;

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

**Meta API:**
```js
fixture`Authentication`.page`https://example.com/login`.meta({
  "allure.label.epic": "Web interface",
  "allure.label.feature": "Essential features",
});

test.meta({
  "allure.label.story": "Authentication",
})("sign in", async (t) => {
  // ...
});
```

**Title annotations:**
```js
fixture`Authentication`.page`https://example.com/login`;

test(
  "sign in" +
    " @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/v3/navigation/#suite-based-hierarchy):

**Runtime API:**
```js
const { parentSuite, suite, subSuite } = require("allure-js-commons");

fixture`Authentication`.page`https://example.com/login`;

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

**Meta API:**
```js
fixture`Authentication`.page`https://example.com/login`.meta({
  "allure.label.parentSuite": "Tests for web interface",
  "allure.label.suite": "Tests for essential features",
});

test.meta({
  "allure.label.subSuite": "Tests for authentication",
})("sign in", async (t) => {
  // ...
});
```

**Title annotations:**
```js
fixture`Authentication`.page`https://example.com/login`;

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

### Divide a test into steps

To [create steps and sub-steps](/docs/steps/), use the `step()` function from `allure-js-commons`. See the [reference](/docs/testcafe-reference/#test-steps) for the full API.

In addition, the reporter automatically captures TestCafe actions such as `t.click()`, `t.typeText()`, and `t.expect()` as steps. These automatic steps appear nested under any enclosing explicit step. To disable automatic action capture, set [`captureActionsAsSteps: false`](/docs/testcafe-configuration/#captureActionsAsSteps) in the reporter config.

```js
const { step, logStep, Status } = require("allure-js-commons");

fixture`Authentication`.page`https://example.com/login`;

test("sign in", async (t) => {
  await step("Fill credentials", async () => {
    await step("Enter login", async (ctx) => {
      await ctx.parameter("login", "demo-user");
      await t.typeText("#login", "demo-user");
    });
    await t.typeText("#password", "secret").click("#submit");
  });
  await logStep("Verified", Status.PASSED);
});
```

### Hooks

The runtime API works in TestCafe fixture and test hooks. Labels, steps, and attachments added inside hooks are recorded as part of the owning test result.

**Fixture hooks:**
```js
const { owner, step, attachment } = require("allure-js-commons");

fixture`Authentication`.page`https://example.com/login`
  .beforeEach(async (t) => {
    await owner("alice");
    await step("Dismiss cookie banner", async () => {
      await t.click("#accept-cookies");
    });
  })
  .afterEach(async () => {
    await step("Capture session log", async () => {
      await attachment("session.log", "...", "text/plain");
    });
  });

test("sign in", async (t) => {
  // ...
});
```

**Test hooks:**
```js
const { severity, tag, step } = require("allure-js-commons");

fixture`Authentication`.page`https://example.com/login`;

test
  .before(async (t) => {
    await tag("smoke");
    await step("Seed credentials", async () => {
      await t.typeText("#username", "demo");
    });
  })
  .after(async () => {
    await severity("critical");
  })("sign in", async (t) => {
  // ...
});
```

### Describe parametrized tests

A typical way to implement [parametrized tests](/docs/v3/readability/#parametrized-tests) in TestCafe is to define a test in a loop. To display a parameter value in the test report, pass it to the [`parameter()`](/docs/testcafe-reference/#parametrized-tests) function.

Additionally, any meta key that is not an Allure-specific key (`allure.*`) and whose value is a scalar string, number, boolean, or bigint is automatically added as a test parameter. This lets you annotate test variants with plain meta without any runtime API calls:

**Runtime API:**
```js
const { parameter } = require("allure-js-commons");

fixture`Authentication`.page`https://example.com/login`;

for (const login of ["johndoe", "johndoe@example.com"]) {
  test(`sign in as ${login}`, async () => {
    await parameter("login", login);
    await parameter("timestamp", new Date().toISOString(), { excluded: true });
    // ...
  });
}
```

**Meta API:**
```js
fixture`Authentication`.page`https://example.com/login`;

for (const [login, role] of [
  ["johndoe", "user"],
  ["admin", "admin"],
]) {
  test.meta({ login, role })(`sign in as ${login}`, async (t) => {
    // login and role appear as parameters in the report
    // ...
  });
}
```

### Set labels globally

Any [labels](/docs/testcafe-reference/#label), including custom ones, can be set via environment variables in your operating system. Here is an example (assuming you use the `npm` package manager):

**MacOS/Linux:**
```bash
export ALLURE_LABEL_epic=WebInterface
npx testcafe --config-file .testcaferc.cjs
```

**Windows:**
```powershell
$Env:ALLURE_LABEL_epic = "WebInterface"
npx testcafe --config-file .testcaferc.cjs
```

Alternatively, set `globalLabels` in the reporter config (runner API only) to apply labels to every test result in the run. See [Configuration](/docs/testcafe-configuration/#globalLabels).

### Attach files

Reports generated by Allure can include any files attached to the test using `allure.attachment()` or `allure.attachmentPath()`. See [Attachments](/docs/attachments/).

```js
const { attachment, attachmentPath } = require("allure-js-commons");
const { ContentType } = require("allure-js-commons");
const path = require("node:path");

fixture`Authentication`.page`https://example.com/login`;

test("sign in", async () => {
  // ...

  await attachment("Server response", JSON.stringify({ status: "ok" }), "application/json");

  await attachmentPath("Config file", path.join(__dirname, "config.txt"), ContentType.TEXT);
});
```

#### Automatic screenshots and videos

When TestCafe is configured to capture screenshots or record videos, the reporter automatically attaches them to the corresponding test result. No additional configuration is needed beyond your TestCafe setup.

Screenshots taken on failure are attached to the failed action step when TestCafe provides enough information to link them. Explicitly requested screenshots via `t.takeScreenshot()` appear as attachments on the `takeScreenshot` step.

When running tests across multiple browsers, screenshots and videos are attributed to the appropriate per-browser result. A `Browser` parameter is also automatically added to each result, showing the browser name.

#### Quarantine mode

When TestCafe runs tests in [quarantine mode](https://testcafe.io/documentation/403841/guides/intermediate-guides/quarantine-mode), the reporter attaches a `Quarantine` JSON file summarizing the result of each attempt. If the test is marked unstable by TestCafe — meaning it passed after earlier failures in the same run — the reporter also adds an `"unstable"` tag to the result automatically.

#### Warnings and errors

If TestCafe produces warnings during a test, they are automatically attached as a `Warnings` text file on the affected result. When a test produces multiple errors, or when a single error lacks complete diagnostic information, a formatted `Errors` text attachment is added to the result.

### Select tests via a test plan file

When the `ALLURE_TESTPLAN_PATH` environment variable is set and points to an existing file, the `createAllureTestPlanFilter()` helper filters tests to only those listed in the plan.

Create an Allure test plan file:

```json
{
  "version": "1.0",
  "tests": [
    {
      "selector": "tests/auth.test.js#Authentication#sign in"
    },
    {
      "id": "42"
    }
  ]
}
```

The `selector` format is `<file>#<fixture>#<test>`, where `<test>` is the clean test name with any title annotations stripped. Tests can also be matched by their Allure ID, set via the `"allure.id"` meta key or `@allure.id=<value>` title annotation. Because filtering runs before the test body executes, the runtime `allureId()` function cannot be used to register a test for plan-based selection.

Set `ALLURE_TESTPLAN_PATH`, then run normally. The filter only takes effect when the variable is set:

**MacOS/Linux:**
```bash
export ALLURE_TESTPLAN_PATH=testplan.json
npx testcafe --config-file .testcaferc.cjs
```

**Windows:**
```powershell
$Env:ALLURE_TESTPLAN_PATH = "testplan.json"
npx testcafe --config-file .testcaferc.cjs
```

Test plan filtering requires a JS/CJS config file or runner API so that `createAllureTestPlanFilter()` can be wired up as the TestCafe `filter` function. It is not possible to use this feature with a JSON config file.

### Environment information

To include environment details on the report's main page, pass key-value pairs in the `environmentInfo` option when using the runner API. See [Configuration](/docs/testcafe-configuration/#environmentInfo).
