Skip to content

Property-Based Composition Testing

Test method — instantiates Composability Testing and Validation

Encodes what must stay true of a composition as an executable property, then auto-generates many combinations hunting for one that breaks it.

Most tests check one hand-written combination against one hand-written expected answer. Property-Based Composition Testing inverts that: instead of an example, you write a property — a statement that must hold for every combination in some domain — and hand a generator the job of trying to falsify it. Its defining move is universal quantification made executable: the property is both the specification of the composability claim and the oracle that judges it, and a randomized generator (with automatic shrinking of any failure to a minimal reproducer) actively searches the combination space for a counterexample. It does not sample a fixed plan; it probes adversarially, run after run, and its currency is not "these cases passed" but "across thousands of generated combinations, the property never broke — and here is the exact combination that did."

Example

A retail platform has a promotions engine where discounts stack: percentage-off coupons, buy-one-get-one rules, loyalty points, gift cards, and tax all compose in some order onto a cart. Testing individual promotions is easy; the danger is their combinations. So the team writes properties that must hold for any stack of promotions applied to any cart: the final price is never negative; the final price never exceeds the pre-discount subtotal; applying the same promotion twice never charges the customer less than applying it once with double weight. Then a generator manufactures random carts and random promotion stacks — thousands per run — and checks each property.

On one run the generator finds a cart where a percentage coupon applied after a gift card, combined with a rounding rule, drives the total to −$0.03. The framework shrinks the failing case to its bare minimum: one item, one coupon, one gift card, at a specific price ending in a half-cent. That minimal reproducer is worth more than the original noisy failure — it hands engineering the exact interaction, stripped of everything irrelevant.

How it works

  • State the property, not the example. Write invariants that must hold over the whole domain of compositions ("for all carts and all promotion stacks, price ≥ 0"), which doubles as the composability claim.
  • Generate combinations, don't enumerate them. A randomized generator produces valid compositions across the domain — biased, if configured, toward boundaries and pathological inputs where interactions cluster.
  • Search adversarially. Each generated combination is an attempt to break the property; the generator's job is to find the counterexample, not to confirm the happy path.
  • Shrink the failure. On a break, automatically reduce the failing combination to the smallest input that still fails, so the reproducer isolates the interaction rather than burying it.

Tuning parameters

  • Generator distribution — uniform random versus boundary-biased versus domain-guided. Boundary bias finds edge interactions faster; uniform gives less-biased coverage of the interior.
  • Run count / effort — how many combinations to generate per property per run. More runs raise the odds of catching a rare-triggering interaction but cost time; unlike a fixed plan, coverage here is probabilistic.
  • Property strength — how tight the asserted invariant is. A strong property (exact equality) catches more but is harder to state without false alarms; a loose one (a bound) is robust but lets subtle drift through.
  • Shrinking aggressiveness — how hard the framework works to minimize a counterexample. Aggressive shrinking yields cleaner reproducers at the cost of extra runs after each failure.

When it helps, and when it misleads

Its strength is reach with little authoring effort: one well-chosen property stands in for thousands of example tests and finds interaction defects a human would never think to write down — especially the ones lurking at numeric boundaries, empty inputs, and unusual orderings. The shrinking step makes every failure land as a minimal, debuggable reproducer.

Its failure mode is that the method is only as good as the property. A property too weak to be violated passes forever while saying nothing (green does not mean safe; it means "not yet falsified within the run budget"), and a property that encodes a wrong belief will flag correct behavior as a bug. The classic misuse is mistaking passing runs for a proof — property-based testing is falsification, not verification[1], and absence of a counterexample is not a certificate. The guarding discipline is to review properties as carefully as production code, keep the generator honest about the real input domain, and treat a long clean run as strong evidence rather than closure.

How it implements the components

  • invariant_and_safety_oracle — the property predicate is the executable oracle, evaluated automatically on every generated combination.
  • adversarial_combination_probe — the generator, with boundary bias and shrinking, actively hunts for the combination that breaks the property rather than confirming expected ones.
  • composability_claim_scope — a universally-quantified property states the claim's scope precisely: it holds for all combinations in the generator's declared domain, and only there.

It generates and judges but does not budget coverage across a modeled factor space — that principled allocation belongs to Combinatorial Sampling Strategy — and it does not stage a controlled release; the promotion-through-contexts gate belongs to Staged Integration Sandbox.

Editorial Notes

Form Classification

Form family: Experiment, Test & Rehearsal

Rationale: Property-Based Composition Testing operates as an active test, trial, simulation, drill, or rehearsal that generates evidence through a deliberate attempt or perturbation because it encodes what must stay true of a composition as an executable property, then auto-generates many combinations hunting for one that breaks it.

Independent corroboration: The frozen evidence defines Property-Based Composition Testing as 'Encodes what must stay true of a composition as an executable property, then auto-generates many combinations hunting for one that breaks it', so its operative form is Experiment, Test & Rehearsal.

Review outcome: Independent reviewer agreement; high confidence.

Origin Attribution

Primary origin: Computer Science & Software Engineering

Origin pattern: Cross-disciplinary synthesis

Present-day reach: Specialized

Rationale: Property-Based Composition Testing is most plausibly rooted in the computer_science tradition because its characteristic form depends on algorithms, data structures, formal interfaces, and software-system practice. The assignment tracks that formative lineage, not the many settings in which the mechanism can now be applied.

Related originating lineages:

  • Mathematics — The mathematics tradition materially shaped Property-Based Composition Testing through its own practice of formal definition, proof, mapping, and quantitative structure.

Review resolution: Both blind reviewers agree that computer science is the primary origin. Explicit reconciliation resolves origin mode disagreement, encyclopedia synthesis disagreement. Formative alternate lineages are retained as mathematics; later breadth of use is recorded separately as domain_reach=specialized, while origin_mode=cross_disciplinary_synthesis describes the relationship among origin lineages.

Encyclopedia synthesis: The exact catalogued form synthesizes established practice rather than reproducing a single standard historical label.

Review outcome: Reconciled after independent review; high confidence.

References

[1] Claessen, Koen, Hughes, John. “QuickCheck: A Lightweight Tool for Random Testing of Haskell Programs”. Proceedings of the Fifth ACM SIGPLAN International Conference on Functional Programming 268–279 (2000). Presents QuickCheck as randomized testing that searches for counterexamples to stated properties, not as proof that a universal property is true. registry ↩