Jest Integration
Relevant source files
The following files were used as context for generating this wiki page:
The @fast-check/jest package provides a seamless integration of the fast-check property-based testing framework with the Jest testing framework. Its primary purpose is to simplify the process of writing property-based tests by enriching Jest's native test and it functions with a .prop method. This allows developers to easily define properties and leverage fast-check's powerful value generation and shrinking capabilities directly within their Jest test suites.
This integration supports both synchronous and asynchronous properties, various Jest test modifiers like .skip and .concurrent, and advanced features such as a worker-based runner for handling potentially blocking synchronous code.
Sources: packages/jest/README.md
Getting Started
Installation
To begin, install the package as a development dependency. It requires jest to be installed in the project.
npm install --save-dev @fast-check/jest
Sources: packages/jest/README.md:14-16
Configuration
For optimal reproducibility, it is highly recommended to run Jest with the --show-seed command-line option. This ensures that Jest will always print the seed used for the test run, which fast-check will automatically adopt, making it easy to reproduce any failures. This feature requires Jest version 29.2.0 or higher.
jest --show-seed
Sources: packages/jest/README.md:20-24, packages/jest/CHANGELOG_1.X.md:162-163
Core API: test.prop and it.prop
The package exports enriched versions of Jest's test and it functions. These functions are extended with a .prop method, which is the entry point for defining a property-based test.
The .prop method accepts an array of fast-check arbitraries or a record (object) of arbitraries, followed by a predicate function. The predicate will be executed multiple times with values generated by the arbitraries.
Basic Usage
Properties can be defined by passing an array of arbitraries or a record of named arbitraries. The predicate can be either synchronous or asynchronous.
import { test, fc } from '@fast-check/jest';
// Using an array of arbitraries
test.prop([fc.string(), fc.string(), fc.string()])('should detect the substring', (a, b, c) => {
return (a + b + c).includes(b);
});
// Using a record of named arbitraries
test.prop({ a: fc.string(), b: fc.string(), c: fc.string() })('should detect the substring', ({ a, b, c }) => {
return (a + b + c).includes(b);
});
// Asynchronous property
test.prop([fc.nat()])('should handle async properties', async (a) => {
await new Promise(resolve => setTimeout(resolve, 0));
return a >= 0;
});
Sources: packages/jest/README.md:28-41, packages/jest/test/jest-fast-check.spec.ts:133-145
Advanced Features
Test Modifiers
@fast-check/jest supports Jest's standard test modifiers, allowing you to control test execution in a familiar way. These modifiers can be chained before .prop.
The following diagram illustrates how modifiers can be chained with test or it.
This diagram shows that modifiers like .concurrent and .failing can be chained together before calling .prop.
Sources: packages/jest/README.md:57-60, packages/jest/test/jest-fast-check.spec.ts:285-428
| Modifier | Description |
|---|---|
.prop | Defines a property-based test. |
.skip | Skips the execution of the property-based test. |
.only | Runs only this property-based test within the suite. |
.todo | Marks the property-based test as a "to-do" item. |
.concurrent | Runs the property-based test concurrently with others. |
.failing | Inverts the test outcome. The test passes if the property fails, and fails if it succeeds. |
Sources: packages/jest/README.md:57-75, packages/jest/test/jest-fast-check.spec.ts:285-428
Custom Parameters and Seed Management
You can forward custom fast-check parameters by passing a fc.Parameters object as the second argument to .prop. This is useful for setting a specific seed, increasing the number of runs, or configuring other fast-check options.
import { test, fc } from '@fast-check/jest';
// Replay a test with a specific seed
test.prop([fc.nat(), fc.nat()], { seed: 4242 })('should replay the test for the seed 4242', (a, b) => {
return a + b === b + a;
});
The seed for a property run is determined with the following precedence:
- Jest's
--seedCLI option: Highest priority. - Local
fc.Parameters: Aseedprovided in the options object to.prop. - Global
fc.configureGlobal: A seed set globally forfast-check. - Random: If no seed is specified, one is generated randomly.
Sources: packages/jest/README.md:53-55, packages/jest/test/jest-fast-check.spec.ts:241-283, packages/jest/CHANGELOG_1.X.md:162-163
Timeout Handling
@fast-check/jest respects Jest's timeout configurations. If a property takes too long to execute, it will be interrupted. The timeout duration is resolved based on a clear precedence order.
The following flowchart shows the timeout precedence, from highest to lowest.
This diagram illustrates that a timeout defined directly on a test call has the highest priority.
Sources: packages/jest/test/jest-fast-check.spec.ts:431-527, packages/jest/CHANGELOG_1.X.md:104-105
Experimental Worker-based Runner
@fast-check/jest includes an experimental worker-based runner that can execute properties in an isolated process. This is particularly useful for terminating properties that contain synchronous, long-running code, such as an infinite loop, which would otherwise block the main thread.
To use it, you must import init from @fast-check/jest/worker.
The following diagram shows the interaction flow when using the worker runner.
Usage
ES Modules:
import { init, fc } from '@fast-check/jest/worker';
const { test, expect } = await init(new URL(import.meta.url));
test.prop([fc.constant(null)])('should pass', (value) => {
expect(value).toBe(null);
});
CommonJS:
const { init, fc } = require('@fast-check/jest/worker');
const { pathToFileURL } = require('node:url');
const { test, expect } = init(pathToFileURL(__filename));
test.prop([fc.constant(null)])('should pass', (value) => {
expect(value).toBe(null);
});
This feature is marked as experimental and may not fully support transformations performed via Jest's transform steps.
Sources: packages/jest/README.md:77-108, packages/jest/CHANGELOG_1.X.md:118-119
Versioning and Compatibility
The compatibility of @fast-check/jest with its peer dependencies is crucial for it to function correctly.
| Package | Minimal Version Requirements |
|---|---|
@fast-check/jest | ^2.0.0 |
jest | >=26.5.0 |
fast-check | ^3.0.0 or ^4.0.0 |
node | >=14.15.0 and <18, >=18.17.0 and <19, >=20 |
The package also has optional peer dependencies on @fast-check/worker, @jest/expect, and @jest/globals.
Sources: packages/jest/README.md:112-121, packages/jest/package.json:48-62, packages/jest/CHANGELOG.md:46-47
Deprecated API
In versions prior to 1.4.0, the integration used a different API: itProp and testProp were separate functions imported from the package. This API was deprecated in version 1.7.3 and completely removed in 2.0.0. The current API, it.prop and test.prop, was introduced in version 1.4.0 and is the recommended way to write property-based tests.
Sources: packages/jest/CHANGELOG.md:50-51, packages/jest/CHANGELOG_1.X.md:73-74, 133-134
Summary
The @fast-check/jest package provides a robust and developer-friendly bridge between fast-check and Jest. By extending Jest's native test and it functions, it offers a familiar and intuitive API (.prop) for writing property-based tests. With support for advanced features like test modifiers, timeout handling, and an experimental worker runner, it empowers developers to thoroughly test their code against a wide range of inputs while remaining within the Jest ecosystem.