Runners and Configuration
Relevant source files
The following files were used as context for generating this wiki page:
- packages/fast-check/src/check/runner/Runner.ts
- packages/fast-check/src/check/runner/configuration/Parameters.ts
- packages/fast-check/src/check/runner/configuration/QualifiedParameters.ts
- packages/fast-check/src/check/runner/configuration/GlobalParameters.ts
- packages/fast-check/src/check/property/IProperty.ts
The fast-check library uses a system of Runners to execute property-based tests. These runners are highly configurable through a hierarchical parameter system, allowing for fine-grained control over test execution. This document details the architecture of the runners, the configuration parameters available, and how they interact to provide a robust testing experience.
The core responsibility of a runner is to execute a given property a specified number of times (numRuns), report success, or find a counter-example and shrink it to the smallest possible failing case.
Configuration System
Configuration in fast-check is handled through a layered approach, allowing settings to be specified globally, at the runner level, or on a per-property basis. These layers are merged to produce a final, "qualified" set of parameters that governs the execution of a test.
This diagram illustrates how different configuration sources are resolved into the final QualifiedParameters used by the runner.
Global Parameters
Global parameters can be set using fc.configureGlobal(...) and are retrieved using readConfigureGlobal(). These settings apply to all fast-check assertions unless overridden by more specific configurations.
Key functions for global configuration:
configureGlobal(params: GlobalParameters): void: Sets the global parameters.readConfigureGlobal(): GlobalParameters: Reads the currently set global parameters.resetConfigureGlobal(): void: Resets the global parameters to their default state.
Sources: packages/fast-check/src/check/runner/configuration/GlobalParameters.ts:10-41
Runner-Level Parameters
Parameters can be passed directly to assertion functions like fc.assert or fc.asyncAssert. These parameters override any global settings for that specific assertion. The Parameters<T> type defines the acceptable options at this level.
Sources: packages/fast-check/src/check/runner/configuration/Parameters.ts:10-101
Qualified Parameters
QualifiedParameters represents the final, resolved configuration that the runner will use for execution. It is the result of merging global and runner-level parameters. The function resolveQualifiedParameters is responsible for this merging, providing default values for any unspecified options.
Sources: packages/fast-check/src/check/runner/configuration/QualifiedParameters.ts:62-140
Key Configuration Parameters
The behavior of a runner is controlled by a variety of parameters. The table below summarizes the most important ones, their purpose, and default values.
| Parameter | Type | Description |
|---|---|---|
seed | number | A seed for the random number generator to ensure reproducibility. If not provided, it's generated based on Date.now(). |
numRuns | number | The number of times to run the property. Defaults to 100. |
maxSkips | number | The maximum number of skips due to unmet preconditions (fc.pre) before the test fails. Defaults to 100. |
timeout | number | The maximum time in milliseconds for the entire execution, including all runs and shrinking. |
path | string | A path to a failing case, used to replay a specific failure. |
unbiased | boolean | When set to true, it uses an unbiased arbitrary, which can be useful for specific scenarios but may be slower to find edge cases. |
verbose | boolean or VerbosityLevel | Controls the level of logging during the test run. |
interruptAfterTimeLimit | number | Maximum time in milliseconds for the whole assert execution. Fails if the execution takes longer. |
skipAllAfterTimeLimit | number | All runs will be skipped after this time limit has been reached. |
endOnFailure | boolean | When set to true, the test process will exit on the first failure. |
Sources: packages/fast-check/src/check/runner/configuration/Parameters.ts:10-101, packages/fast-check/src/check/runner/configuration/QualifiedParameters.ts:8-60
The Runner Execution Flow
The runner orchestrates the entire property testing process. It can be executed synchronously (run) or asynchronously (runAsync). The core logic remains the same in both cases.
The following flowchart outlines the execution process within a fast-check runner.
Runner and Property Interaction
The runner does not execute the user's code directly. Instead, it interacts with an IProperty (or IAsyncProperty) object. This interface abstracts the property's logic, including value generation and predicate execution.
The IProperty interface defines two key methods:
generate(mrng: Random): Value<T>: Generates a new value for the property using the provided random number generator.run(v: T): string | null: Executes the property's predicate with a generated valuev. It returnsnullon success or an error message string on failure.
// From packages/fast-check/src/check/property/IProperty.ts
export interface IProperty<T, IsAsync extends boolean = false> {
isAsync(): IsAsync;
generate(mrng: Random, runId?: number): Value<T>;
shrink(value: Value<T>): Stream<Value<T>>;
run(v: T): PreconditionFailure | Promise<PreconditionFailure | string | null> | string | null;
}
Sources: packages/fast-check/src/check/property/IProperty.ts:12-25
The runner calls property.generate() to get a value and then passes it to property.run(). If run() indicates a failure, the runner uses property.shrink() to find a smaller counter-example.
Execution Result
The runner returns a RunDetails object, which contains comprehensive information about the execution, including:
failed: A boolean indicating if the test failed.numRuns: The number of successful runs.numSkips: The number of skipped runs.numShrinks: The number of shrinks performed on failure.seed: The seed used for the run.counterexample: The smallest failing input found.counterexamplePath: The path to reproduce the failure.error: The error message from the failure.
Sources: packages/fast-check/src/check/runner/Runner.ts:16-23
Conclusion
The runner and configuration system are central to fast-check's power and flexibility. By providing a layered configuration model, developers can easily set defaults at a global level while overriding them for specific tests. The runner itself implements the core property-based testing loop, from value generation and execution to shrinking and reporting, interacting with IProperty objects to remain decoupled from the specific test logic. This architecture enables reproducible, configurable, and robust property-based testing.