Skip to main content

Property-Based Testing

Updated 2 min read

Share this page

Send the link, quote the definition with a link back, or show it as a card on your own site.

https://softwaredictionary.org/terms/property-based-testing

In short

Property-based testing checks that a rule holds for many automatically generated inputs, instead of only for a handful of examples written by hand.

What is property-based testing?

Property-based testing is a technique where you describe a property, a rule that should be true for every valid input, and a library generates hundreds of inputs to try to break it. Typical properties are that reversing a list twice gives back the original list, or that sorted output is in order and contains the same elements as the input. The approach began with QuickCheck for Haskell around 2000 and is now available for most languages.

You tell the framework what kind of inputs to generate, such as integers, strings, or lists of user records, and it runs the test many times with random data. Generators deliberately include tricky edge cases, like empty lists, zero, negative numbers, very long strings, and unusual Unicode characters. When a failure appears, the framework shrinks the input, simplifying it step by step to the smallest case that still fails, so you debug [0, -1] instead of a list with 200 elements.

It's like testing a lock by hiring someone to try thousands of odd-shaped keys and report the simplest one that opens it, instead of only trying the three keys you own. Property-based testing works especially well for parsers and serializers, where decoding an encoded value must return the original, and for sorting, math, data transformations, pure functions, and comparing an optimized implementation against a simple reference one.

Property-based testing is often confused with fuzz testing. Both generate inputs automatically, but fuzzing usually throws large volumes of random or malformed data at a program for hours to find crashes and security holes, while property-based testing runs quickly in the normal test suite and checks specific correctness rules. It complements example-based unit tests rather than replacing them, since clear examples are still the best documentation of expected behavior.

Key takeaways

  • You state a rule that must hold for all valid inputs, not a single expected output.
  • The framework generates many inputs, including tricky edge cases.
  • Failing inputs are shrunk to the smallest example that still fails.
  • Round-trip properties such as decode(encode(x)) == x are a classic starting point.
  • It checks correctness rules, while fuzzing mainly hunts for crashes.

Example

A round-trip property tested with Python's Hypothesis librarypython
import json
from hypothesis import given, strategies as st

# Property: turning a dict into JSON and back must give the same dict.
# The library generates hundreds of dicts, including empty and unusual ones,
# and shrinks any failing input to the smallest example.
@given(st.dictionaries(keys=st.text(), values=st.integers()))
def test_json_round_trip(data):
    assert json.loads(json.dumps(data)) == data

Readers ask

What is a property in property-based testing?

A property is a statement that should be true for every valid input, such as the output of a sort having the same length as its input. The test checks that statement against many generated inputs.

What is shrinking?

Shrinking is the step where the framework takes a failing input and repeatedly simplifies it, for example by removing items or making numbers smaller, until it finds the minimal input that still fails. This makes the bug much easier to understand.

See also

Spotted a mistake or something missing on this page?Suggest an edit

Read a random page
Open today's review
Switch to the dark theme
Read this page in Türkçe

More

Settings