fast-check

repository·main·Indexed 26 days ago

https://github.com/dubzzz/fast-check

A property-based testing framework for JavaScript and TypeScript that verifies code properties across automatically generated inputs. It includes the core fast-check library and official integrations for testing frameworks including Jest (@fast-check/jest), Vitest (@fast-check/vitest), and AVA (@fast-check/ava), as well as specialized utilities like @fast-check/poisoning for prototype poisoning detection and @fast-check/packaged for npm publication file management.

Tokens
78.6K
Snippets
219
Records
518
Agent score
90%

What's inside fast-check

  1. Introduction to fast-check

    main
    fast-check is a property-based testing library for JavaScript and TypeScript. Unlike traditional example-based testing where you manually provide specific inputs, fast-check automatically generates hundreds of test cases for your assertions. When a failure is found, it automatically 'shrinks' the input to find the smallest possible case that still reproduces the bug.
  2. Overview of the fast-check ecosystem

    main

    The fast-check ecosystem consists of official and third-party extensions and plugins that add additional capabilities to the core library.

    Stability Warning:

    • Official packages (marked with ⭐) are maintained and guaranteed by the fast-check team.
    • Non-official packages (marked with 🥇, 🥈, 🌗, or ⚠️) are third-party and do not come with the same stability or maintenance guarantees from the core team.
  3. Use @fast-check/ava for AVA testing

    main
    The @fast-check/ava package is the official integration for using fast-check property-based testing with the AVA test runner. It replaces the legacy ava-fast-check package. This package provides support for pre-conditions (fc.pre) and ensures seed computation is aligned with the core fast-check library.
  4. Explore advanced fast-check topics and API reference

    main

    Once you have mastered the basics via tutorials, you can use the following documentation sections to deepen your knowledge:

    • Core Blocks: Reference for properties, runners, and arbitraries.
    • Configuration: Instructions for fine-tuning fast-check to match your project's constraints.
    • Advanced: Deep dives into model-based testing, race conditions, and more.
    • API Reference: An exhaustive list of every exported symbol in the library.
  5. Understand fast-check configuration precedence

    main

    fast-check uses a hierarchical configuration model:

    1. Per-assertion configuration: Passed directly to fc.assert(property, { ... }). This has the highest priority and overrides all other settings.
    2. Global configuration: Set via fc.configureGlobal({ ... }). This applies to all assertions that do not provide their own local configuration.

    A common pattern is to set conservative defaults globally (e.g., tighter timeouts for CI environments) and widen them locally for specific tests that require more runs, larger input sizes, or a specific seed.

  6. Understand the difference between example-based and property-based testing

    main

    Property-based testing differs from traditional example-based testing in how it asserts code behavior:

    • Example-based testing: Asserts how code behaves on one specific set of inputs and expects a specific outcome.
    • Property-based testing: Asserts a relationship (a "property") between inputs and outputs that should hold for all valid sets of inputs. In fast-check, a property is a function that takes randomly-generated inputs, performs a test, and throws an error if the property is violated.

    This approach allows you to focus on the general behaviors of your code rather than manually picking specific test values.

  7. Understand Composite Arbitraries in fast-check

    main

    Composite arbitraries allow you to assemble structured values by combining smaller, existing arbitraries. Instead of generating random structures, you define a specific shape (like an array, object, or typed array) and provide child arbitraries to fill that shape.

    Key features of composites include:

    • Size control: Most composites support minLength and maxLength bounds, along with a size modifier to scale the magnitude of generated values.
    • Two-dimensional shrinking: When a test fails, fast-check shrinks the structure (e.g., reducing array length or object keys) and the contents (shrinking individual elements using their own arbitraries) independently. This ensures counterexamples collapse to the minimal failing value.
  8. Install and use @fast-check/poisoning

    main

    The @fast-check/poisoning package provides utilities to detect and revert prototype poisoning in JavaScript.

    Requirements:

    • Node.js version ≥20.19.0

    Available Utilities:

    • assertNoPoisoning: Asserts that defaults known at import time have not been changed.
    • restoreGlobals: Restores defaults to their original state.
  9. Fast-check track record and bug detection examples

    main

    Fast-check has been used to identify critical bugs and CVEs in major open-source projects. It is effective at finding edge cases in algorithms, serialization libraries, and security-sensitive code (such as prototype poisoning in lodash).

    Key projects where bugs were confirmed via fast-check include:

    • Test Runners: jest, jasmine
    • Utility Libraries: underscore.js, query-string, left-pad, javascript-stringify
    • Data Formats: js-yaml, yaml
    • Security/Auth: node-jsonwebtoken
    • Algorithms: javascript-algorithms
  10. Understand Primitive Arbitraries and Constraints

    main

    Primitive arbitraries (strings, numbers, booleans, dates, and bigints) are the foundational building blocks of fast-check. All composite, combiner, and fake data arbitraries are eventually derived from these primitives.

    Key behaviors to note:

    • Constraint Inheritance: Constraints applied to a primitive (such as number ranges, string character sets, or date bounds) are inherited by any complex arbitrary built on top of them. Narrowing a primitive's constraints directly narrows the possible values of all downstream arbitraries.
    • Shrinking Behavior: When a test fails, fast-check shrinks primitive values toward specific canonical "simple" targets. Recognizing these targets helps in interpreting counterexamples in the terminal.
  11. Advanced testing techniques in fast-check

    main

    Beyond simple property testing with fc.assert, fast-check provides advanced capabilities for complex testing scenarios:

    • Model-based testing: Used for stateful systems where bugs appear only after specific sequences of operations. You define legal commands, and fast-check explores the space of operation sequences.
    • Race conditions: Used to find bugs caused by the order of asynchronous callback resolutions. fast-check provides a scheduler to deterministically explore these interleavings.
    • Fuzzing: Used for continuous bug hunting. You can extend fast-check into a continuous fuzz loop to hunt for counterexamples beyond the default budget or across multiple runs.
    • Fake data generation: Used to generate large volumes of realistic-looking values for seeding environments or staging datasets outside of a standard property-test context.