Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions website/docs/en/api/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,10 @@
"type": "dir-section-header",
"name": "rstest",
"label": "Rstest Utility"
},
{
"type": "dir-section-header",
"name": "node-api",
"label": "Node API"
}
]
1 change: 1 addition & 0 deletions website/docs/en/api/node-api/_meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
["reporter"]
120 changes: 120 additions & 0 deletions website/docs/en/api/node-api/reporter.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
title: Reporter
---

# Reporter API

The Reporter API allows you to create custom test result processors and output formatters. This interface is experimental and may change in future versions.

> **Note**: For usage examples and configuration guidance, see the [Reporters guide](/guide/basic/reporters).

## Using custom reporter

Create a custom reporter by implementing the `Reporter` interface:

```ts
import type { Reporter, TestFileResult } from '@rstest/core';

const customReporter: Reporter = {
onTestFileStart(test) {
console.log(`Starting: ${test.testPath}`);
},

onTestFileResult(result) {
console.log(`Finished: ${result.testPath}`);
},

onTestRunEnd({ results, duration }) {
console.log(`All tests completed in ${duration.totalTime}ms`);
},
};
```

Use the custom reporter in your configuration:

```ts
import { defineConfig } from '@rstest/core';
import { customReporter } from './path/to/custom-reporter';

export default defineConfig({
reporters: [customReporter],
});
```

## Interface overview

The `Reporter` interface provides lifecycle hooks for test execution. Each hook is called at specific points during the test run.

> **Important**: For the most up-to-date interface definition and complete type signatures, please refer to the [source code](https://github.com/web-infra-dev/rstest/blob/main/packages/core/src/types/reporter.ts).

### Hook categories

- **File-level hooks**: `onTestFileStart`, `onTestFileReady`, `onTestFileResult`
- **Suite-level hooks**: `onTestSuiteStart`, `onTestSuiteResult`
- **Case-level hooks**: `onTestCaseStart`, `onTestCaseResult`
- **Run-level hooks**: `onTestRunEnd`, `onUserConsoleLog`, `onExit`

### Basic interface structure

```ts
interface Reporter {
onTestFileStart?(test: TestFileInfo): void;
onTestFileReady?(test: TestFileInfo): void;
onTestFileResult?(test: TestFileResult): void;
onTestSuiteStart?(test: TestSuiteInfo): void;
onTestSuiteResult?(result: TestResult): void;
onTestCaseStart?(test: TestCaseInfo): void;
onTestCaseResult?(result: TestResult): void;
onTestRunEnd?(context: TestRunEndContext): MaybePromise<void>;
onUserConsoleLog?(log: UserConsoleLog): void;
onExit?(): void;
}
```

## Examples

### Simple custom reporter

```ts
import type { Reporter } from '@rstest/core';

const simpleReporter: Reporter = {
onTestFileStart(test) {
console.log(`📁 ${test.testPath}`);
},

onTestCaseResult(result) {
const status = result.status === 'pass' ? '✅' : '❌';
console.log(`${status} ${result.name}`);
},

onTestRunEnd({ results }) {
const passed = results.filter((r) => r.status === 'pass').length;
const failed = results.filter((r) => r.status === 'fail').length;
console.log(`\n📊 ${passed} passed, ${failed} failed`);
},
};
```

### File output reporter

```ts
import { writeFileSync } from 'node:fs';
import type { Reporter } from '@rstest/core';

const jsonReporter: Reporter = {
onTestRunEnd({ results }) {
const report = {
timestamp: new Date().toISOString(),
results: results.map((r) => ({
path: r.testPath,
status: r.status,
duration: r.duration,
errors: r.errors,
})),
};

writeFileSync('test-report.json', JSON.stringify(report, null, 2));
},
};
```
144 changes: 31 additions & 113 deletions website/docs/en/config/test/reporters.mdx
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
---
overviewHeaders: []
---

# reporters

- **Type:**

```ts
type Reporter = ReporterName | [ReporterName, ReporterOptions];

type Reporters = Reporter | Reporter[];
```

Expand All @@ -22,156 +17,79 @@ process.env.GITHUB_ACTIONS === 'true'

- **CLI:** `--reporter=<name> --reporter=<name1>`

Customize the reporter type.

## Built-in Reporters

### Default reporter
Configure which reporters to use for test result output.

By default, Rstest displays test run status, results, and summary information in the terminal.
### Usage

Output example:
#### Basic example

```bash
✓ test/index.test.ts (2)

Test Files 1 passed
Tests 2 passed
Duration 112ms (build 19ms, tests 93ms)
```

### Verbose reporter

The default reporter only outputs test case information when tests fail or run slowly. The verbose reporter will output all test case information after test completion.
You can specify reporters in the `rstest.config.ts` file or via the CLI.

import { Tab, Tabs } from '@theme';

<Tabs defaultValue='rstest.config.ts'>
<Tab label="CLI">

```bash
npx rstest --reporter=verbose
npx rstest --reporter=default
```

</Tab>
<Tab label="rstest.config.ts">

```ts
import { defineConfig } from '@rstest/core';

export default defineConfig({
reporters: 'verbose'
reporters: 'default',
});
```
</Tab>
</Tabs>

With verbose reporter, Rstest outputs:

```bash
✓ test/index.test.ts (2) 2ms
✓ Index > should add two numbers correctly (1ms)
✓ Index > should test source code correctly (1ms)

Test Files 1 passed
Tests 2 passed
Duration 112ms (build 19ms, tests 93ms)
```

### GitHub Actions reporter

The GitHub Actions reporter outputs error messages in the form of [workflow commands](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-commands#setting-an-error-message) when tests fail.

#### Output example

When tests fail, the GitHub Actions reporter outputs information in a format similar to:

```bash
::error file=src/index.ts,line=4,col=17,title=test/index.test.ts > should add two numbers correctly::expected 2 to be 4
```

These outputs are parsed by GitHub Actions and generate comments at the corresponding locations.

![rstest-github-actions-example](https://assets.rspack.rs/rstest/assets/rstest-github-actions-example.jpg)

#### Auto-enablement

When no reporter is manually set, Rstest automatically enables this reporter when it detects a GitHub Actions environment (`process.env.GITHUB_ACTIONS` is `'true'`).
</Tab>
</Tabs>

#### Manual enablement
#### Multiple reporters

You can also manually enable this reporter:
You can use multiple reporters to output test results in different formats simultaneously. This is useful when you want both console output and a file report for CI/CD pipelines.

<Tabs defaultValue='rstest.config.ts'>
<Tab label="CLI">
```bash
npx rstest --reporter=github-actions
```
</Tab>
<Tab label="rstest.config.ts">
```ts
```ts title=rstest.config.ts
import { defineConfig } from '@rstest/core';

export default defineConfig({
reporters: ['github-actions']
reporters: ['default', 'junit'],
});
```
</Tab>
</Tabs>

### JUnit reporter
#### Configuring reporters with options

The JUnit reporter supports outputting test reports in JUnit XML format, making it easy to integrate with CI/CD.
Many reporters support configuration options. Pass them as a tuple `[reporterName, options]`:

<Tabs defaultValue='rstest.config.ts'>
<Tab label="CLI">
```bash
npx rstest --reporter=junit
```
</Tab>
<Tab label="rstest.config.ts">
```ts
```ts title=rstest.config.ts
import { defineConfig } from '@rstest/core';

export default defineConfig({
reporters: [['junit', { outputPath: './junit.xml' }]]
reporters: [
['default', { verbose: true }],
['github-actions', { verbose: true }],
['junit', { outputPath: './test-results.xml' }],
],
});
```
</Tab>
</Tabs>

#### Options
#### Using custom reporters

- `outputPath`: Configure the output path for the report. If not specified, it will output to the console.
You can create and use custom reporters by providing a reporter class or object that implements the reporter interface:

```ts title="rstest.config.ts"
```ts title=rstest.config.ts
import { defineConfig } from '@rstest/core';
import { CustomReporter } from './custom-reporter';

export default defineConfig({
reporters: [['junit', { outputPath: './junit.xml' }]],
reporters: [CustomReporter],
});
```

#### Output example

The JUnit reporter generates XML format as follows:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="rstest tests" tests="3" failures="1" errors="1" skipped="1" time="0.3" timestamp="2024-01-01T00:00:00.000Z">
<testsuite name="test1.test.ts" tests="3" failures="1" errors="1" skipped="1" time="0.3" timestamp="2024-01-01T00:00:00.000Z">
<testcase name="should pass" classname="test1.test.ts" time="0.1">
</testcase>
<testcase name="should fail" classname="test1.test.ts" time="0.2">
<failure message="Test failed" type="AssertionError">expected 'hi' to be 'hii' // Object.is equality - Expected + Received - hii + hi at test1.test.ts:10:21</failure>
</testcase>
<testcase name="should skip" classname="test1.test.ts" time="0.0">
<skipped/>
</testcase>
</testsuite>
</testsuites>
```

The JUnit reporter maps test case execution status to JUnit test status:
### Related documentation

- `pass`: Test passed
- `fail`: Test failed, generates `<failure>` tag
- `skip`: Test skipped, generates `<skipped>` tag
- `todo`: Test todo, generates `<skipped>` tag
- [Reporters guide](/guide/basic/reporters) - Usage examples and built-in reporter details
- [Reporter API reference](/api/node-api/reporter) - Custom reporter implementation
1 change: 1 addition & 0 deletions website/docs/en/guide/basic/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"test-filter",
"snapshot",
"projects",
"reporters",
"vscode-extension",
"upgrade-rstest"
]
Loading
Loading