Introduction
fast-check brings property-based testing to the JavaScript ecosystem, inspired by Haskell's QuickCheck. Instead of writing individual test cases with hardcoded inputs, you describe properties that should hold for all valid inputs. fast-check then generates hundreds of random inputs, finds failing cases, and automatically shrinks them to the simplest reproduction.
What fast-check Does
- Generates random test inputs from a rich library of built-in arbitraries (numbers, strings, arrays, objects, dates, and more)
- Tests that properties hold across hundreds of automatically generated cases per run
- Shrinks failing inputs to the smallest example that still triggers the failure
- Replays specific failures deterministically using seed values
- Integrates with Jest, Vitest, Mocha, and any assertion library
Architecture Overview
fast-check centers on two concepts: arbitraries (generators that produce random values with shrinking capabilities) and properties (assertions parameterized by generated values). The runner executes a property by repeatedly sampling from its arbitraries. When a failure is found, the shrinker systematically reduces each input dimension to find a minimal counterexample. Seeds ensure reproducibility across runs.
Self-Hosting & Configuration
- Install:
npm install --save-dev fast-check - Import and use directly in test files alongside your existing test runner
- Configure run parameters:
fc.assert(property, { numRuns: 1000, seed: 42 })for more thorough or reproducible testing - Create custom arbitraries with
fc.record(),fc.oneof(), andfc.chain()for domain-specific data - Use
fc.pre()to filter generated values that do not meet preconditions
Key Features
- Rich built-in arbitrary library covering primitives, collections, recursive structures, and more
- Automatic shrinking produces minimal counterexamples without manual effort
- Seed-based replay lets CI reproduce exact failures from logs
- Model-based testing for stateful systems using
fc.commands()andfc.modelRun() - Async property support for testing promise-based and async/await code
Comparison with Similar Tools
- QuickCheck (Haskell) — The original property-based testing library; fast-check adapts the concept for JavaScript with a modern API
- Hypothesis (Python) — Python's property-based testing; fast-check provides equivalent capabilities for the JS/TS ecosystem
- JSVerify — Earlier JS property testing library; fast-check offers better shrinking, more arbitraries, and active maintenance
- Jest/Vitest — Example-based test runners; fast-check complements them by discovering edge cases you would not write manually
- Faker.js — Generates realistic fake data; fast-check generates structured data specifically designed for shrinking and property verification
FAQ
Q: How is property-based testing different from example-based testing? A: Example-based tests verify specific input-output pairs. Property-based tests verify that a property holds for all valid inputs, automatically discovering edge cases like empty arrays, negative numbers, or Unicode strings.
Q: How many test cases does fast-check run by default?
A: 100 runs per property by default. You can increase this with numRuns for more thorough testing or decrease it for faster feedback.
Q: Can I use fast-check with my existing test framework?
A: Yes. fast-check works with Jest, Vitest, Mocha, Jasmine, and any runner. Just call fc.assert() inside your test functions.
Q: What is shrinking? A: When fast-check finds a failing input, it automatically tries smaller or simpler values to find the minimal input that still fails. This makes debugging much easier by removing irrelevant complexity.