---
title: "Property-based testing"
description: "State a rule that must hold for every input, then let a generator hunt for the smallest input that breaks it."
group: concept
terms:
  - "property-based testing"
  - "property test"
  - "property tests"
  - "PBT"
sources:
  - https://github.com/Effect-TS/effect/blob/effect%404.0.0-rc.117/packages/effect/src/unstable/arbitrary/Arbitrary.ts
  - https://github.com/joelhooks/rat-stack/tree/main/packages/events/test
  - https://x.com/davidkpiano/status/2105670489091834297
---

An example test checks one input you picked. A property test states a rule that must hold for every input, generates many inputs, and when one fails, shrinks it to a small counterexample.

Effect 4 ships its own engine in `effect/unstable/arbitrary`. `Arbitrary.schema` derives a generator from an Effect `Schema`, so the same schema that defines a capability's contract also generates its test inputs. `Arbitrary.checkEffect` checks a pure or effectful property and "shrinks the first falsification." [Arbitrary.ts](https://github.com/Effect-TS/effect/blob/effect%404.0.0-rc.117/packages/effect/src/unstable/arbitrary/Arbitrary.ts) `@effect/vitest` exposes it as `it.prop` and `it.effect.prop`.

The [capture-first](/lore/capture-first) events cartridge is tested this way. For any generated request, exactly one event is recorded, the response is unchanged, and the request body never reaches the event. For any query string, credential and email keys never survive. A failing sink never changes the response.

A property earns its place only if breaking the code breaks it. When the events tests were first written, removing `token` from the sensitive-key list did not fail them: the property compared the filter with the same function it was testing. A second property with an independent list of sensitive keys closed the gap, and the failure shrank to a single input, `"secret": "token"`. See [tests that earn their place](/lore/tests-that-earn-their-place).

For sequences of actions, use [model-based testing](/lore/model-based-testing).

## Lore on this page

- [Cartridges](/lore/cartridges)
