fast-check Documentation

Property based testing framework for JavaScript (like QuickCheck) written in TypeScript

RAW Doc

File: examples/README.md

Examples based on `fast-check`

This directory gathers multiple examples of properties you might come with when using fast-check.

Try online with CodeSandbox.

Teach yourself property based through examples

Examples by category

Following examples show how you could think about properties given algorithms ranging from basic pure functions returning easy to assess outputs to complex state machines.

Simple data structures

101 for property based:

  • decompPrime - Returns the list of prime factors corresponding to the input value
  • fibonacci - Returns the item at a given position in the sequence of Fibonacci
  • indexOf - Returns the position of the first occurrence of pattern in text
  • sort - Returns a sorted copy of the input array

Recursive structures

Let's see how to generate recursive inputs using letrec, memo or even none of them:

  • isSearchTree - Returns true if the tree is a binary search tree, false otherwise

Misc

Various algorithms to have more random examples:

  • knight - Multi dimensional dichotomy given as a coding exercise
  • mazeGenerator - Maze generator
  • roman - Convert from and to roman notation for numbers

State machines to user interfaces

Property based testing applied to state machines or user interfaces:

  • MusicPlayer - Simple music player with play, pause, addTrack and next

Race conditions

Property based testing used to detect race conditions in various kind of JavaScript snippets:

  • AutocompleteField - An autocomplete field written in React providing suggestions as soon as possible
  • Counter - Increment a counter stored in a DB using compare-and-swap
  • DebouncedAutocomplete - An autocomplete field written in React providing suggestions in a debounced way (uses timers)
  • dependencyTree - Fetch recursively dependencies for a npm package
  • TodoList - Simple todolist React app
  • UserProfilePage - A simple React component loading user profile on mount

Rules of property based

  1. Properties do not replace examples, they are just an extra layer of tests
  2. Properties can be used at any level: unit, integration, end-to-end

Tricks to find properties

  1. Characteristics independent of the inputs

Examples:

for any floating point number d, Math.floor(d) is an integer

for any integer n, Math.abs(n) โ‰ฅ 0

  1. Characteristics derived from the inputs

Examples:

for any a and b integers the average of a and b is between a and b

for any array โ€” data, sorted(data) and data contain the same elements

  1. Restricted set of inputs with useful characteristics

Examples:

for any prime number p, its decomposition into prime factors is itself

for any a, b and c strings the concatenation of a, b and c always contains b

  1. Characteristics on combination of functions

Examples:

for any file f, unzip(zip(f)) is the original file

for any a, b numbers lcm(a, b) * gcd(a, b) equals a * b

  1. Comparison with a simpler implementation

File: packages/worker/README.md

`@fast-check/worker`

Provide built-ins to run predicates directly within dedicated workers




Why?

fast-check alone is great but what if it led your code into an infinite and synchronous loop for such inputs? In such case, it would neither be able to shrink the issue, nor to report any for you as the single threaded philosophy at the root of JavaScript will prevent it from anything except waiting for the main thread to come back.

This package tends to provide a way to run easily your properties within dedicated workers automatically spawed by it.

Example

Here are some of the changes you will have to do:

  • hoist properties so that they get declared on the root scope
  • replace fc.property by property coming from propertyFor()
  • replace fc.assert by assert coming from @fast-check/worker for automatic cleaning of the workers as the test ends
  • transpilation has not been addressed yet but it may probably work
  • in theory, if you were only using propertyFor and assert without any external framework for test, it and others, the separation of the property from the assertion would be useless as the check for main thread is fully handled within @fast-check/worker itself so no hoisting needing in such case
js
import { test } from '@jest/globals';
import fc from 'fast-check';
import { isMainThread } from 'node:worker_threads';
import { assert, propertyFor } from '@fast-check/worker';

const property = propertyFor(new URL(import.meta.url)); // or propertyFor(pathToFileURL(__filename)) in commonjs
const p1 = property(fc.nat(), fc.nat(), (start, end) => {
  // starting a possibly infinite loop
  for (let i = start; i !== end; ++i) {
    // doing stuff...
  }
});

if (isMainThread) {
  test('should assess p1', async () => {
    await assert(p1, { timeout: 1000 });
  });
}

Refer to the tests defined test/main.spec.ts for a living example of how you can use this package with a test runner such as Jest.

Extra options

The builder of properties propertyFor accepts a second parameter to customize how the workers will behave. By default, workers will be shared across properties. In case you want a more isolation between your runs, you can use:

js
const property = propertyFor(new URL(import.meta.url), { isolationLevel: 'predicate' });
// Other values:
// - "file": Re-use workers cross properties (default)
// - "property": Re-use workers for each run of the predicate. Not shared across properties!
// - "predicate": One worker per run of the predicate

By default, workers will receive the generated values from their parent thread. In some cases, such sending is made impossible as the generated values include non-serializable pieces. In such cases, you can opt-in to generate the values directly within the workers by using:

js
const property = propertyFor(new URL(import.meta.url), { randomSource: 'worker' });
// Other values:
// - "main-thread": The main thread will be responsible to generate the random values and send them to the worker thread. It unfortunately cannot send any value that cannot be serialized between threads. (default)
// - "worker": The worker is responsible to generate its own values based on the instructions provided by the main thread. Switching to a worker mode allows to support non-serializable values, unfortunately it drops all shrinking. capabilities.

Minimal requirements

  • Node โ‰ฅ14.18.0(1)(2)(3)
  • TypeScript โ‰ฅ4.1 (optional)

(1): worker_threads alone would only require Node โ‰ฅ10.5.0, but our usage of require(node:*) forces us to request at least Node โ‰ฅ14.18.0

(2): this package targets ES2020 specification which is quite well supported (more than 94%) by any Node โ‰ฅ14.5.0

(3): this package requires a version of node able to understand package.json#exports, supported by any Node โ‰ฅ12.17.0


File: packages/vitest/README.md

`@fast-check/vitest`

Bring the power of property based testing framework fast-check into Vitest.
@fast-check/vitest simplifies the integration of fast-check into Vitest.




Getting Started

Install @fast-check/vitest:

bash
npm install --save-dev @fast-check/vitest

In order to work properly, @fast-check/vitest requires vitest to be installed.

Examples

The library comes with two modes, both powered by fast-check:

  • One-time random mode โ€“ A lightweight approach that introduces controlled randomness into your tests while keeping runs reproducible.
  • Property-based testing mode โ€“ A full-fledged property-based testing approach leveraging the full capabilities of fast-check.

One-time random mode

This mode extends Vitest's default test and it functions, allowing you to introduce controlled randomness into your tests while ensuring failures remain reproducible. This makes it easier to debug flaky tests and avoid irreproducible failures due to randomness.

Unlike property-based testing, this mode does not run tests multiple times or attempt shrinking when failures occur. Instead, it provides a determistic way to introduce randomness when needed.

javascript
import { test, fc } from '@fast-check/vitest';
import { expect } from 'vitest';

// You can provide a fixed seed to force a replay by adding this line:
// >>  fc.configureGlobal({ seed })
// Eventually you can disable shrinking capabilities with:
// >>  fc.configureGlobal({ endOnFailure: false })
// >>  // or combine it with the one above if you need both

test('test relying on randomness', ({ g }) => {
  // Arrange
  const user = {
    firstName: g(fc.string),
    lastName: g(fc.string),
  };

  // Act
  const displayName = computeDisplayName(user);

  // Assert
  expect(displayName).toContain(user.firstName);
});

test('test not relying on randomness', () => {
  // your test
});

Full property-based mode

For more extensive testing, @fast-check/vitest also provides full support for property-based testing. This mode enables exhaustive, randomized testing by generating a variety of inputs and detecting edge cases automatically.

javascript
import { test, fc } from '@fast-check/vitest';

// for all a, b, c strings
// b is a substring of a + b + c
test.prop([fc.string(), fc.string(), fc.string()])('should detect the substring', (a, b, c) => {
  return (a + b + c).includes(b);
});

// same property but using named values
test.prop({ a: fc.string(), b: fc.string(), c: fc.string() })('should detect the substring', ({ a, b, c }) => {
  return (a + b + c).includes(b);
});

Please note that the properties accepted by @fast-check/vitest as input can either be synchronous or asynchronous (even just PromiseLike instances).

Seamless integration with Vitest's `beforeEach` / `afterEach`

Vitest's beforeEach and afterEach hooks are natively integrated into predicates. They are called respectively before and after each execution of the predicate. If a predicate runs n times, beforeEach will be called n times before it and afterEach n times after it. The only caveat is that cleanup functions returned by beforeEach on the first predicate execution are deferred until the end of the test, as they are handled by vitest's own teardown mechanism. All other cleanups run between predicate executions as expected.

Advanced

If you want to forward custom parameters to fast-check, test.prop accepts an optional fc.Parameters (more).

@fast-check/vitest also comes with .only, .skip, .todo and .concurrent from vitest. It also accepts more complex ones such as .concurrent.skip.

javascript
import { it, test, fc } from '@fast-check/vitest';

test.prop([fc.nat(), fc.nat()], { seed: 4242 })('should replay the test for the seed 4242', (a, b) => {
  return a + b === b + a;
});

test.skip.prop([fc.string()])('should be skipped', (text) => {
  return text.length === [...text].length;
});

describe('with it', () => {
  it.prop([fc.nat(), fc.nat()])('should run too', (a, b) => {
    return a + b === b + a;
  });
});

Minimal requirements

@fast-check/vitest vitest fast-check Node
0.4 ^4.1.0 ^3.0.0 || ^4.0.0 โ‰ฅ20.19.0(2)
0.3 ^1 || ^2 || ^3 || ^4 ^3.0.0 || ^4.0.0 โ‰ฅ20.19.0(2)
0.2 ^1 || ^2 || ^3 || ^4(1) ^3.0.0 || ^4.0.0 โ‰ฅ18(3)
0.1 >=0.28.1 <1.0.0 || ^1 || ^2(4) || ^3(5) ^3.0.0 || ^4.0.0(6) โ‰ฅ14.16.0(3)
0.0 >=0.28.1 <1.0.0 || ^1 ^3.0.0 โ‰ฅ14.16.0(3)

More details...

  1. Official support for version 4.x of vitest starts at 0.2.3.
  2. Requires support for require(esm).
  3. Same support as vitest.
  4. Official support for version 2.x of vitest starts at 0.1.2.
  5. Official support for version 3.x of vitest starts at 0.1.5.
  6. Official support for version 4.x of fast-check starts at 0.1.6.

File: packages/poisoning/README.md

`@fast-check/poisoning`

Set of utilities to ease detection and revert of poisoning




Why?

In JavaScript, "prototype poisoning" is one of the most common source for CVEs or zero days. It allows attackers to change the behaviour of some defaults like Array.prototype.map, Map, Set... so that they behave differently and can be leveraged for evil stuffs. This package can be used in addition to fast-check in order to detect poisoning that may occur during your property based tests.

Easy to use

The package comes with:

  • assertNoPoisoning: assert that the defaults known when first importing the package in your code have not been changed
  • restoreGlobals: restore the defaults so that any change that could have been detected by assertNoPoisoning will be resolved

Minimal requirements

  • Node โ‰ฅ20.19.0

File: packages/packaged/README.md

`@fast-check/packaged`

Utility package removing any files that will not be part of the final bundle published to npm registry




Why?

When publishing packages to npm registry, it is quite easy to forget about some files. It also happens many times that we want somehow to check the packaged bundle in some of our tests but totally forget that some files have not been added to the bundle and so that the final user will actually never be able to run this code.

This package mostly try to prevent this issue. It can easily be used in monorepos to emulate the bundled package when used against other packages of the monorepo to make sure others do not depend on internals or non published stuff.

Easy to use

Run the following command at the root of your package to drop any file that will not make it in the final bundle published to npm.

bash
# With npm
npx -p @fast-check/packaged packaged
# With pnpm
pnpm --package=@fast-check/packaged dlx packaged
# With yarn
yarn dlx -p @fast-check/packaged packaged

โš ๏ธ You may want to try with --dry-run flag first to give it a try.

It also comes with some extra flags:

  • --dry-run: do not drop any file or directory from the file system and only print what would have been removed
  • --keep <name>: keep a root-level file or directory matching the exact name (not a glob pattern, can be specified multiple times, e.g. --keep node_modules --keep src)

Simple API

js
import { computePublishedFiles, removeNonPublishedFiles } from '@fast-check/packaged';

// Compute the list of all files that would be part of the bundle
// if we attempted to publish the packge defined at .
const publishedFilesRoot = await computePublishedFiles('.');

// Compute the list of all files that would be part of the bundle
// if we attempted to publish the packge defined at ./sub-directory
const publishedFilesSubDirectory = await computePublishedFiles('./sub-directory');

// Run the deletion of unwanted files
const { kept, removed } = await removeNonPublishedFiles('.', { dryRun: false, keep: [] });
// kept and removed are arrays of strings
// they may contain files or directories

Minimal requirements

@fast-check/packaged node
0.6.x โ‰ฅ20.19.0(1)

More details...

  1. Requires support for require(esm).

File: packages/jest/README.md

`@fast-check/jest`

Bring the power of property based testing framework fast-check into Jest.
@fast-check/jest simplifies the integration of fast-check into Jest testing framework.




Getting Started

Install @fast-check/jest:

bash
npm install --save-dev @fast-check/jest

In order to work properly, @fast-check/jest requires jest to be installed.

We also highly recommend users to launch their tests using the --show-seed option provided by Jest. It ensures Jest will always print the seed by itself (requires Jest โ‰ฅ29.2.0).

sh
jest --show-seed

Example

javascript
import { test, fc } from '@fast-check/jest';

// for all a, b, c strings
// b is a substring of a + b + c
test.prop([fc.string(), fc.string(), fc.string()])('should detect the substring', (a, b, c) => {
  return (a + b + c).includes(b);
});

// Or the exact same test but based on named parameters
test.prop({ a: fc.string(), b: fc.string(), c: fc.string() })('should detect the substring', ({ a, b, c }) => {
  return (a + b + c).includes(b);
});

The it and test functions returned by @fast-check/jest are just enriched versions of the ones coming from jest itself. They both come with .prop.

Please note that the properties accepted by @fast-check/jest as input can either be synchronous or asynchronous (even just PromiseLike instances). In other words, the predicate passed as the last argument can be asynchronous.

Remark: it and test have been introduced in 1.4.0. You have to refer to Deprecated API if you are using a version of @fast-check/jest <1.4.0.

Advanced

Support for variations of `test` and `it`

If you want to forward custom parameters to fast-check, test.prop and its variants accept an optional fc.Parameters (more).

@fast-check/jest also comes with support for .only, .skip, .todo and .concurrent from jest. It also accepts more complex ones such as .concurrent.failing or .concurrent.only.failing.

javascript
import { it, test, fc } from '@fast-check/jest';

// With custom `fc.Parameters`, here { seed: 4242 }
test.prop([fc.nat(), fc.nat()], { seed: 4242 })('should replay the test for the seed 4242', (a, b) => {
  return a + b === b + a;
});

// With .skip
test.skip.prop([fc.string()])('should be skipped', (text) => {
  return text.length === [...text].length;
});

// With it version
describe('with it', () => {
  it.prop([fc.nat(), fc.nat()])('should run too', (a, b) => {
    return a + b === b + a;
  });
});

Experimental worker-based runner

The following feature is experimental! When used it makes runners able to kill long running synchonous code. Meaning that it will make fast-check able to kill infinite loops blocking the main thread. So far, the feature does not fully support transformations performed via transform steps defined with jest.

The CommonJS approach would be:

js
const { init, fc } = require('@fast-check/jest/worker');
const { pathToFileURL } = require('node:url');

const { test, expect } = init(pathToFileURL(__filename));
// can also be passed options such as isolationLevel: init(pathToFileURL(__filename), {})

test.prop([fc.constant(null)])('should pass', (value) => {
  expect(value).toBe(null);
});

The ES Modules approach would be:

js
import { init, fc } from '@fast-check/jest/worker';

const { test, expect } = await init(new URL(import.meta.url));
// can also be passed options such as isolationLevel: init(new URL(import.meta.url), {})

test.prop([fc.constant(null)])('should pass', (value) => {
  expect(value).toBe(null);
});

โš ๏ธ Do not forget to add the await before init for the ES Module version!

Extra setup for `@fast-check/worker` 0.6.0 and later

Since @fast-check/worker is an ESM-only package, running it under Jest in CommonJS mode requires babel-jest to transpile it. Install the following dependencies:

bash
npm install --save-dev babel-jest @babel/core @babel/preset-env

Then add a babel.config.cjs at the root of your project:

js
module.exports = {
  presets: [['@babel/preset-env', { targets: { node: 'current' }, modules: 'commonjs' }]],
};

And update your Jest configuration to use babel-jest while excluding @fast-check/worker from the ignore patterns:

js
module.exports = {
  transform: {
    '^.+\\.[t|j]sx?$': 'babel-jest',
  },
  transformIgnorePatterns: ['/node_modules/(?!(?:@fast-check/worker)/)'],
};

This ensures @fast-check/worker gets transpiled to CommonJS by Babel instead of being skipped. Without it, Jest will fail to load the ESM-only package.

For ES Modules mode, no extra setup is needed โ€” just make sure to run Jest with --experimental-vm-modules:

bash
node --experimental-vm-modules node_modules/jest/bin/jest.js

Minimal requirements

@fast-check/jest jest fast-check node
^2.0.0 >=26.5.0(1)(2) ^3.0.0 >=14.15.0(3) and <18, >=18.17.0 and <19(4), >=20
^1.0.0 >=26.5.0(1)(2) ^3.0.0 >=14.15.0(3) and <18, >=18.17.0 and <19(4), >=20
  • (1) any version of jest should be greater or equal than 26.5.0 if you are using commonjs
  • (2) in order to use esm build, you may need to enable experimental features of node, see here
  • (3) >=14.15.0 is the minimal requirements for jest, >=12.17.0 is the one for @fast-check/jest
  • (4) timeout defined on jest might not be properly applied to fast-check for node 18 (until 18.17.0) and node 19, see #4004

File: packages/fast-check/README.md

Getting started

Hands-on tutorial and definition of Property Based Testing: ๐Ÿ see tutorial. Or directly try it online on our pre-configured CodeSandbox.

Property based testing frameworks check the truthfulness of properties. A property is a statement like: for all (x, y, ...) such that precondition(x, y, ...) holds predicate(x, y, ...) is true.

Install the module with: pnpm add -D fast-check or yarn add fast-check --dev or npm install fast-check --save-dev

Example of integration in mocha:

js
import fc from 'fast-check';

// Code under test
const contains = (text, pattern) => text.indexOf(pattern) >= 0;

// Properties
describe('properties', () => {
  // string text always contains itself
  it('should always contain itself', () => {
    fc.assert(fc.property(fc.string(), (text) => contains(text, text)));
  });
  // string a + b + c always contains b, whatever the values of a, b and c
  it('should always contain its substrings', () => {
    fc.assert(
      fc.property(fc.string(), fc.string(), fc.string(), (a, b, c) => {
        // Alternatively: no return statement and direct usage of expect or assert
        return contains(a + b + c, b);
      }),
    );
  });
});

In case of failure, the test raises a red flag. Its output should help you to diagnose what went wrong in your implementation. Example with a failing implementation of contain:

text
1) should always contain its substrings
    Error: Property failed after 1 tests (seed: 1527422598337, path: 0:0): ["","",""]
    Shrunk 1 time(s)
    Got error: Property failed by returning false

    Hint: Enable verbose mode in order to have the list of all failing values encountered during the run

Integration with other test frameworks: ava, jasmine, jest, mocha and tape.

More examples: simple examples, fuzzing and against various algorithms.

Useful documentations:

Why should I migrate to fast-check?

fast-check has initially been designed in an attempt to cope with limitations I encountered while using other property based testing frameworks designed for JavaScript:

  • Types: strong and up-to-date types - thanks to TypeScript
  • Extendable: easy map method to derive existing arbitraries while keeping shrink [more] - some frameworks ask the user to provide both a->b and b->a mappings in order to keep a shrinker
  • Extendable: kind of flatMap-operation called chain [more] - able to bind the output of an arbitrary as input of another one while keeping the shrink working
  • Extendable: precondition checks with fc.pre(...) [more] - filtering invalid entries can be done directly inside the check function if needed
  • Extendable: easily switch from fake data in tests to property based with fc.gen() [more] - generate random values within your predicates
  • Smart: ability to shrink on fc.oneof [more] - surprisingly some frameworks don't
  • Smart: biased by default - by default it generates both small and large values, making it easier to dig into counterexamples without having to tweak a size parameter manually
  • Debug: verbose mode [more][tutorial] - easier troubleshooting with verbose mode enabled
  • Debug: replay directly on the minimal counterexample [tutorial] - no need to replay the whole sequence, you get directly the counterexample
  • Debug: custom examples in addition of generated ones [more] - no need to duplicate the code to play the property on custom examples
  • Debug: logger per predicate run [more] - simplify your troubleshoot with fc.context and its logging feature
  • Unique: model based approach [more][article] - use the power of property based testing to test UI, APIs or state machines
  • Unique: detect race conditions in your code [more][tutorial] - shuffle the way your promises and async calls resolve using the power of property based testing to detect races
  • Unique: simplify user definable corner cases [more] - simplify bug resolution by asking fast-check if it can find an even simpler corner case

For more details, refer to the documentation in the links above.

Trusted

fast-check has been trusted for years by big projects like: jest, jasmine, fp-ts, io-ts, ramda, js-yaml, query-string...

Powerful

It also proved useful in finding bugs among major open source projects such as jest, query-string... and many others.

Compatibility

Here are the minimal requirements to use fast-check properly without any polyfills:

fast-check node ECMAScript version TypeScript (optional)
4.x โ‰ฅ12.17.0(1) ES2020 โ‰ฅ5.0
3.x โ‰ฅ8(2) ES2017 โ‰ฅ4.1(3)
2.x โ‰ฅ8(2) ES2017 โ‰ฅ3.2(4)
1.x โ‰ฅ0.12(2) ES3 โ‰ฅ3.0(4)

More details...

  1. Even if version 12.x should support most of the ES2020 features that will be leveraged by the version 4, we recommend relying at least on version 14.x of Node as it supports all the targeted specification. In addition, we highly encourage switching to still supported LTS versions of Node and not sticking to unsupported versions for too long.
  2. Except for features that cannot be polyfilled - such as bigint-related ones - all the capabilities of fast-check should be usable given you use at least the minimal recommended version of node associated to your major of fast-check.
  3. Require either lib or target โ‰ฅ ES2020 or @types/node to be installed.
  4. Require either lib or target โ‰ฅ ES2015 or @types/node to be installed.

Contributors โœจ

Thanks goes to these wonderful people (emoji key):

Nicolas DUBIEN๐Ÿ’ป ๐Ÿ“– โš ๏ธ ๐Ÿš‡ ๐ŸŽจ ๐Ÿšง Aaron Elligsen๐Ÿ’ป ๐Ÿ“– โš ๏ธ Will Heslam๐Ÿ“– kazchimo๐Ÿ’ป ๐Ÿ“– Brandon Chinn๐Ÿ’ป ๐Ÿ“– Irakli Safareli๐Ÿ“– Andrew Herron๐Ÿ“– ๐Ÿ”Œ
Eric Crosson๐Ÿ“– ๐Ÿ’ป burrscurr๐Ÿ“– JC (Jonathan Chen)๐Ÿ“– Larry Botha๐Ÿ“– ๐Ÿ’ป โš ๏ธ Roman Gusev๐Ÿ“– Tim Wisniewski๐Ÿ“– Brais Piรฑeiro๐Ÿ’ป โš ๏ธ
Renaud-Pierre Bordes๐ŸŽจ Jemma Nelson๐Ÿ“– John Haugeland๐Ÿ“– Trey Davis๐ŸŽจ Leon Si๐Ÿ“– Gorgi Kosev๐Ÿš‡ mayconsacht๐Ÿ’ป
Simon Friis Vindum๐Ÿ’ป โš ๏ธ Richard Gibson๐Ÿ“– Alan Harper๐Ÿ“– Makien Osman๐Ÿ’ป David Sommerich๐Ÿ’ป โš ๏ธ Diego Pedro๐Ÿ’ป โš ๏ธ Borui Gu๐Ÿ“–
Brian Donovan๐Ÿ“– volrk๐Ÿ’ป ๐Ÿ“– โš ๏ธ tinydylan๐Ÿ’ป โš ๏ธ Caleb Jasik๐Ÿ“– Rulai Hu๐Ÿ“– Afonso Jorge Ramos๐Ÿ“– Tom Jenkinson๐Ÿ“–
phormio๐Ÿ“– Giovanni Gonzaga๐Ÿ’ป โš ๏ธ Tomas Carnecky๐Ÿ’ป Kirill Romanov๐Ÿ’ป ๐Ÿ“– โš ๏ธ Giovanny Gonzรกlez๐Ÿ“– Mark Kulube๐Ÿš‡ Peter Hamilton๐Ÿ’ป
Chinedu Ozodi๐Ÿ“– Gunar Gessner๐Ÿ“– Christian Batchelorโš ๏ธ Tomer Aberbach๐Ÿ’ป ๐Ÿ“– โš ๏ธ 0xflotus๐Ÿ“– Ryan Leonard๐Ÿ’ป ๐Ÿ“– โš ๏ธ Jason Dreyzehner๐Ÿ’ป โš ๏ธ
Matin Zadeh Dolatabad๐Ÿ’ป Juan Juliรกn Merelo Guervรณs๐Ÿ“– Simen Bekkhus๐Ÿ“– Tarjei Skjรฆrset๐Ÿ“– Denis Gorbachev๐Ÿ“– Trevor McCauley๐Ÿ“– Grant Kiely๐Ÿ“–
Attila Veฤerek๐Ÿ’ป ๐Ÿ“– โš ๏ธ Zach Bjornson๐Ÿ’ป ๐Ÿ“– Bennett Perkins๐Ÿ“– Alexandre Oger๐Ÿ“– ๐Ÿ’ป ej shafran๐Ÿ“– Niklas Gruhn๐Ÿ’ป ๐Ÿ’ฌ Patrick Roza๐Ÿ’ป
Cindy Wu๐Ÿ“– Noah๐Ÿ“– James Vaughan๐Ÿ“– ๐Ÿ’ป Alex Errant๐Ÿ’ป andrew jarrett๐Ÿ’ป ๐Ÿ“– Matthias Keckl๐Ÿ“– Dolan Murvihill๐Ÿ’ป
Emi๐Ÿ’ป Russ Biggs๐Ÿ“– adamni21๐Ÿ“– Joseph Junker๐Ÿ“– Aleksey Shelementev๐Ÿ’ป rugk๐Ÿ“– Makien Osman๐Ÿ“–
Jonathan Neidel๐Ÿ“–

This project follows the all-contributors specification. Contributions of any kind welcome! Become one of them

Sponsors ๐Ÿ’ธ

Many individuals and companies offer their financial support to the project, a huge thanks to all of them too ๐Ÿ’“

You can also become one of them by contributing via GitHub Sponsors or OpenCollective.


File: packages/ava/README.md

`@fast-check/ava`

Bring the power of property based testing framework fast-check into AVA.
@fast-check/ava simplifies the integration of fast-check into AVA testing framework.




Getting Started

Install @fast-check/ava:

bash
npm install --save-dev @fast-check/ava

In order to work properly, @fast-check/ava requires ava to be installed.

Example

typescript
import { testProp, fc } from '@fast-check/ava';

// for all a, b, c strings
// b is a substring of a + b + c
testProp('should detect the substring', [fc.string(), fc.string(), fc.string()], (t, a, b, c) => {
  t.true((a + b + c).includes(b));
});

The property is passed AVA's t argument as its first parameter, and the value of each arbitrary for the current test case for the rest of the parameters.

@fast-check/ava supports all of AVA's assertions and like AVA, it supports synchronous and asynchronous functions, including promises, observables, and callbacks. See AVA's documentation for more information.

โš ๏ธ WARNING: When relying on @fast-check/ava, returning true or false in your predicates is not taken into account. The library wants assertions or plans to be defined as ava itself does. Nonetheless you can still use primitives such as fc.pre to cut runs at the middle if some invariants are unmeet: the started plan (if any) will just be ignored.

Advanced

`fast-check` Parameters

testProp accepts an optional fc.Parameters for forwarding custom parameters to fast-check (more).

typescript
import { testProp, fc } from '@fast-check/ava';

testProp(
  'should detect the substring',
  [fc.string(), fc.string(), fc.string()],
  (t, a, b, c) => {
    t.true((a + b + c).includes(b));
  },
  { numRuns: 10 }, // Example of parameters
);

AVA Modifiers

@fast-check/ava also comes with .only, .serial .skip, and .failing modifiers from AVA.

typescript
import { testProp, fc } from '@fast-check/ava';

testProp(
  'should replay the test for the seed 4242',
  [fc.nat(), fc.nat()],
  (t, a, b) => {
    t.is(a + b, b + a);
  },
  { seed: 4242 },
);

testProp.skip('should be skipped', [fc.string()], (t, text) => {
  t.is([...text].length, text.length);
});

AVA `before`/`after` Hooks

@fast-check/ava exposes AVA's before/after hooks:

typescript
import { testProp, fc } from '@fast-check/ava';

testProp.before((t) => {
  connectToDatabase();
});

testProp();
// ... omitted for brevity

testProp.after((t) => {
  closeDatabaseConnection();
});

AVA Execution Context

@fast-check/ava mirror's AVA's procedure for customizing the test execution context:

typescript
import { fc, testProp as anyTestProp, PropertyTestInterface } from '@fast-check/ava';

type TestContext = {
  state: string;
};

const testProp = anyTestProp as PropertyTestInterface<TestContext>;

testProp('should reach terminal state', [fc.string()], (t, received) => {
  // here t is typed as ExecutionContext<TestContext>
  console.log(t.context.state); // logs 'uninitialized'
  // ... omitted for brevity
});

Minimal requirements

@fast-check/ava AVA fast-check node
3.0 ^4 || ^5 || ^6 ^3 || ^4 โ‰ฅ20.19.0(1)
2.0 ^4 || ^5 || ^6 ^3 || ^4 โ‰ฅ12.22.0(2)
1.0 ^4 || ^5 || ^6 ^3 โ‰ฅ12.22.0(2)

More details...

  1. Requires support for require(esm).
  2. As for ava 4.