Home Knowledge Base Property-based testing

Property-based testing

Keywords: property-based testing,software testing


Property-based testing is a software testing approach that tests general properties or invariants that should hold for all inputs rather than testing specific input-output examples — automatically generating diverse test cases and checking whether the specified properties are satisfied, providing more comprehensive testing than example-based tests.

Traditional vs. Property-Based Testing

``python assert add(2, 3) == 5 assert add(0, 0) == 0 assert add(-1, 1) == 0 ``

```python # Property: Addition is commutative for all x, y: add(x, y) == add(y, x)

# Property: Adding zero is identity for all x: add(x, 0) == x

# Property: Addition is associative for all x, y, z: add(add(x, y), z) == add(x, add(y, z)) ```

How Property-Based Testing Works

1. Define Properties: Specify invariants or properties that should hold for the function.

2. Generate Inputs: Testing framework automatically generates diverse test inputs.

3. Execute Tests: Run the function with generated inputs.

4. Check Properties: Verify that properties hold for all generated inputs.

5. Shrinking: If a property fails, automatically minimize the failing input to find the simplest counterexample.

6. Report: Present the minimal failing case to the developer.

Example: Property-Based Testing

from hypothesis import given
import hypothesis.strategies as st

# Function to test:
def reverse_list(lst):
    return lst[::-1]

# Property 1: Reversing twice returns original
@given(st.lists(st.integers()))
def test_reverse_twice(lst):
    assert reverse_list(reverse_list(lst)) == lst

# Property 2: Length is preserved
@given(st.lists(st.integers()))
def test_reverse_length(lst):
    assert len(reverse_list(lst)) == len(lst)

# Property 3: First element becomes last
@given(st.lists(st.integers(), min_size=1))
def test_reverse_first_last(lst):
    reversed_lst = reverse_list(lst)
    assert lst[0] == reversed_lst[-1]
    assert lst[-1] == reversed_lst[0]

# Framework generates hundreds of test cases automatically:
# [], [1], [1,2,3], [-5, 0, 100], [1,1,1,1], etc.

Common Properties to Test

Input Generation Strategies

Shrinking

# Property fails on: [42, -17, 0, 999, -3, 18, 7, -100, 55]
# After shrinking: [0]  # Minimal failing case

# This makes debugging much easier!

Property-Based Testing Frameworks

Applications

Example: Testing a Stack

from hypothesis import given
from hypothesis.stateful import RuleBasedStateMachine, rule
import hypothesis.strategies as st

class StackMachine(RuleBasedStateMachine):
    def __init__(self):
        super().__init__()
        self.stack = []
    
    @rule(value=st.integers())
    def push(self, value):
        self.stack.append(value)
    
    @rule()
    def pop(self):
        if self.stack:
            self.stack.pop()
    
    @rule()
    def check_invariants(self):
        # Property: Stack size is non-negative
        assert len(self.stack) >= 0
        
        # Property: If we push then pop, we get back to original state
        if self.stack:
            original = self.stack.copy()
            value = self.stack[-1]
            self.stack.pop()
            self.stack.append(value)
            assert self.stack == original

# Framework generates random sequences of operations
# and checks properties after each operation

Benefits

Challenges

LLMs and Property-Based Testing

Property-based testing is a powerful complement to example-based testing — it provides broader coverage, finds edge cases automatically, and serves as executable documentation of program properties, leading to more robust and reliable software.


Source: ChipFoundryServicesSearch this topicAsk CFSGPT

property-based testingsoftware testing

Explore 500+ Semiconductor & AI Topics

From EUV lithography to CUDA optimization — search the full knowledge base or chat with our AI assistant.