Test
test defines a test case. It supports chainable modifiers and fixture extension for flexible and powerful test definitions.
Alias: it.
test
- Type:
Defines a test case.
TestOptions
Pass a TestOptions object as the second argument (before the test function) to tune the behavior of a single test:
As a shorthand, you can still pass a number as the last argument to set only the timeout (equivalent to { timeout: n }):
TestOptions accepts:
timeout?: number— per-test timeout in milliseconds. Overridestest.testTimeout.retry?: number— re-runs the test up to this many times if it fails, stopping at the first pass. Overridestest.retry.repeats?: number— re-runs an already-passing test this many extra times; any failure marks the whole case as failed. Each repeat runs the fullbeforeEach/afterEachlifecycle and gets an independentretrybudget.meta?: TaskMeta— added in 0.11.1. Initial JSON-serializable metadata for the test result. If the test is inside adescribewithmeta, it inherits a copy of the suite metadata and test-level keys override inherited keys.
TaskMeta and TaskMetaValue are exported from @rstest/core and allow JSON-serializable values:
In this example, the test result's metadata starts as { owner: 'team-a' }. During execution, the test mutates the same object through context.task.meta, so reporters and the programmatic API receive { owner: 'team-a', startedBy: 'runtime' } on TestResult.meta.
test.each and test.for accept the same options as their second argument and apply it to every generated case.
test.only
Only run certain tests in a test file.
test.skip
Skips certain tests.
Use test.skip when you know at definition time that a test should be skipped. If the decision can only be made while the test is running, call context.skip() from the test context instead. context.skip() stops executing the current test immediately, so code after it will not run, and the test is reported as skipped.
test.todo
Marks certain tests as todo.
test.each
- Type:
Runs the same test logic for each item in the provided array.
You can also use a tagged template literal table syntax for more readable parameterized tests:
The first row defines the parameter names (column headers), and each subsequent row provides the values via template expressions (${...}). Columns are separated by |.
Since the table values are untyped by default, you can provide an explicit generic type parameter for type safety:
You can inject parameters with printf formatting in the test name in the order of the test function parameters.
%s: String%d: Number%i: Integer%f: Floating point value%j: JSON%o: Object%#: 0-based index of the test case%$: 1-based index of the test case%%: Single percent sign ('%')
You can also access object properties with $ prefix:
test.for
- Type:
Alternative to test.each to provide TestContext.
test.for also supports the tagged template literal table syntax:
You can provide an explicit generic type parameter for type safety:
test.fails
Marks the test as expected to fail.
test.concurrent
Runs the test concurrently with consecutive concurrent flags.
test.sequential
Runs the test sequentially (default behavior).
test.runIf
Runs the test only if the condition is true.
test.skipIf
Skips the test if the condition is true.
test.extend
- Type:
test.extend(fixtures: Fixtures)
Extends the test context with custom fixtures and returns a new test API. The original test is not modified — you can have multiple independent extended versions at the same time.
Fixtures are reusable context entries that help you prepare test resources once and inject them where needed. Typical uses include:
- Sharing test data and helper clients (for example, API clients, tokens, test users).
- Wrapping setup/teardown logic in one place instead of repeating it in every test.
- Building fixture dependencies (one fixture can consume another fixture).
- Running global-per-test side effects automatically (for example, logging) via
autofixtures.
The returned API has the same chainable modifiers as test (only, skip, each, concurrent, etc.) and can call .extend() again for further extension.
Fixture function lifecycle
A fixture function receives two parameters:
- context — contains other fixtures as well as
TestContext(task,expect,onTestFinished,onTestFailed). Use object destructuring to declare the dependencies you need. - use — call
await use(value)to pass the fixture value to the test.
Fixture-aware callbacks must list every requested fixture explicitly through direct object destructuring in the callback parameter. Rstest does not infer dependencies from destructuring inside the function body. Object rest properties such as ({ db, ...rest }) and default values such as ({ db = fallback }) or ({ db } = {}) are not supported in test callbacks, fixture functions, or per-test hooks.
Code before await use(value) is setup; code after it is teardown (runs after the test finishes).
Plain value fixtures
If a fixture does not need setup/teardown logic, you can provide a plain value directly:
Accessing TestContext
The first parameter of a fixture function also includes TestContext, so you can read current test information or use expect directly inside a fixture:
Fixture dependencies
A fixture can destructure other fixtures from its first parameter. Rstest automatically initializes them in dependency order and runs teardown in reverse order:
Using fixtures in hooks
beforeEach, afterEach, and a cleanup function returned by beforeEach can request fixtures. Rstest initializes fixtures requested by the test callback before beforeEach, preserving the existing test setup order. A fixture requested only by a hook is initialized before that hook runs. The same instance is shared for the rest of the test attempt, then torn down after all per-test hooks finish.
Declare hook fixture dependencies directly in the callback parameter, for example beforeEach(({ db }) => {}). A named hook context such as beforeEach((context) => {}) remains valid for accessing the regular TestContext, but destructuring context inside the function body does not initialize lazy fixtures.
Core hooks are suite-level APIs, so provide the fixture context type explicitly and register the hook in a suite whose tests use the matching extended test API. If a test in the suite does not provide a requested fixture, Rstest fails that test before invoking the hook and reports the missing fixture:
Automatic fixtures (auto)
Fixtures are lazy by default: they only run when requested through object destructuring by a test or per-test hook callback (or required by another fixture). To make a fixture run for every test automatically — even when no callback requests it — use the tuple syntax with { auto: true }:
Type inference and explicit generics
Fixture types are usually inferred automatically. If inference is not precise enough, provide an explicit generic to test.extend:
Fixture types only take effect on the new API returned by test.extend. The type signature of the original test remains unchanged.
Chainable modifiers
test supports chainable modifiers, so you can use them together. For example:
test.only.runIf(condition)(ortest.runIf(condition).only) will only run the test block if the condition is true.test.skipIf(condition).concurrent(ortest.concurrent.skipIf(condition)) will skip the test block if the condition is true, otherwise run the tests concurrently.test.runIf(condition).concurrent(ortest.concurrent.runIf(condition)) will only run the test block concurrently if the condition is true.test.only.concurrent(ortest.concurrent.only) will only run the test block concurrently.test.for(cases).concurrent(ortest.concurrent.for(cases)) will run the test block concurrently for each case in the provided array.- ......
Types
TestContext
TestContext provides some APIs, context information, and custom fixtures related to the current test.
Use context.task.meta to attach JSON-serializable metadata to the current test result. You can mutate the metadata object or replace it with a new metadata object. Custom reporters and the programmatic API can read this metadata from TestResult.meta:
Use context.skip() to skip a test while it is running. Code after
context.skip() will not execute, and the test is reported as skipped:
You can also extend TestContext with custom fixtures using test.extend.