Agent Skills: Property-Based Testing

|

UncategorizedID: laurigates/claude-plugins/property-based-testing

Install this agent skill to your local

pnpm dlx add-skill https://github.com/laurigates/claude-plugins/tree/HEAD/testing-plugin/skills/property-based-testing

Skill Files

Browse the full folder contents for property-based-testing.

Download Skill

Loading file tree…

testing-plugin/skills/property-based-testing/SKILL.md

Skill Metadata

Name
property-based-testing
Description
|

Property-Based Testing

Expert knowledge for property-based testing - automatically generating test cases to verify code properties rather than testing specific examples.

When to Use This Skill

| Use this skill when... | Use another skill instead when... | |------------------------|----------------------------------| | Testing mathematical properties (commutative, associative) | Writing specific example-based unit tests | | Testing encode/decode roundtrips | Setting up test runner configuration | | Finding edge cases automatically | Doing E2E browser testing | | Validating data transformations and invariants | Analyzing test quality or smells | | Testing API contracts with generated data | Running mutation testing |

Core Expertise

Property-Based Testing Concept

  • Traditional testing: Test specific examples
  • Property-based testing: Test properties that should hold for all inputs
  • Generators: Automatically create diverse test inputs
  • Shrinking: Minimize failing cases to simplest example
  • Coverage: Explore edge cases humans might miss

When to Use Property-Based Testing

  • Mathematical operations (commutative, associative properties)
  • Encoders/decoders (roundtrip properties)
  • Parsers and serializers
  • Data transformations
  • API contracts
  • Invariants and constraints

TypeScript/JavaScript (fast-check)

Installation

# Using Bun
bun add -d fast-check

# Using npm
npm install -D fast-check

Basic Example

import { test } from 'vitest'
import * as fc from 'fast-check'

// Property-based test
test('reverse twice returns original - property based', () => {
  fc.assert(
    fc.property(
      fc.array(fc.integer()), // Generate random arrays of integers
      (arr) => {
        expect(reverse(reverse(arr))).toEqual(arr)
      }
    )
  )
})
// fast-check automatically generates 100s of test cases!

Key Generators (Quick Reference)

| Generator | Description | |-----------|-------------| | fc.integer() | Any integer (with optional min/max) | | fc.nat() | Natural numbers (>= 0) | | fc.float() / fc.double() | Floating-point numbers | | fc.string() | Any string (with optional length) | | fc.emailAddress() | Email format strings | | fc.array(arb) | Arrays of arbitrary type | | fc.record({...}) | Object with typed fields | | fc.boolean() | Boolean values | | fc.constantFrom(...) | Pick from options | | fc.tuple(...) | Fixed-size tuples | | fc.oneof(...) | Union types | | fc.option(arb) | Value or null | | fc.date() | Date objects |

Common Properties to Test

| Property | Pattern | Example | |----------|---------|---------| | Roundtrip | f(g(x)) = x | encode/decode, serialize/parse | | Idempotence | f(f(x)) = f(x) | sort, normalize, format | | Commutativity | f(a,b) = f(b,a) | add, merge, union | | Associativity | f(f(a,b),c) = f(a,f(b,c)) | add, concat | | Identity | f(x, id) = x | multiply by 1, add 0 | | Inverse | f(g(x)) = x | encrypt/decrypt |

Configuration

fc.assert(property, {
  numRuns: 1000,      // Run 1000 tests (default: 100)
  seed: 42,           // Reproducible tests
  endOnFailure: true, // Stop after first failure
})

Preconditions

fc.pre(b !== 0) // Skip cases where b is 0

Python (Hypothesis)

Installation

# Using uv
uv add --dev hypothesis

# Using pip
pip install hypothesis

Basic Example

from hypothesis import given, strategies as st

@given(st.lists(st.integers()))
def test_reverse_twice_property(arr):
    assert reverse(reverse(arr)) == arr
    # Hypothesis automatically generates 100s of test cases!

Key Strategies (Quick Reference)

| Strategy | Description | |----------|-------------| | st.integers() | Any integer (with optional bounds) | | st.floats() | Floating-point numbers | | st.text() | Any string (with optional size) | | st.binary() | Byte strings | | st.lists(strat) | Lists of given strategy | | st.sets(strat) | Unique value sets | | st.dictionaries(k, v) | Dictionaries | | st.booleans() | Boolean values | | st.sampled_from(...) | Pick from options | | st.tuples(...) | Fixed-size tuples | | st.one_of(...) | Union types | | st.dates() / st.datetimes() | Date/time values | | st.builds(Class, ...) | Build objects from strategies |

Configuration

from hypothesis import given, settings, strategies as st

@settings(max_examples=1000, deadline=None)
@given(st.lists(st.integers()))
def test_with_custom_settings(arr):
    assert sort(arr) == sorted(arr)

Assumptions

from hypothesis import assume
assume(b != 0)  # Skip cases where b is 0

Stateful Testing

Hypothesis supports stateful testing via RuleBasedStateMachine for testing sequences of operations against invariants.

Agentic Optimizations

| Context | Command | |---------|---------| | Quick TS test | bunx vitest --dots --bail=1 --grep 'property' | | Quick Python test | uv run pytest -x -q --tb=short -k 'property' | | CI TS test | bunx vitest run --reporter=junit --grep 'property' | | CI Python test | uv run pytest --hypothesis-show-statistics -q | | Reproducible | fc.assert(prop, { seed: 42 }) or @settings(derandomize=True) | | Fast iteration | fc.assert(prop, { numRuns: 50 }) or @settings(max_examples=50) |

For detailed examples, advanced patterns, and best practices, see REFERENCE.md.

See Also

  • vitest-testing - Unit testing framework
  • python-testing - Python pytest testing
  • test-quality-analysis - Detecting test smells
  • mutation-testing - Validate test effectiveness

References

  • fast-check: https://fast-check.dev/
  • Hypothesis: https://hypothesis.readthedocs.io/
  • Property-Based Testing: https://fsharpforfunandprofit.com/posts/property-based-testing/
Property-Based Testing Skill | Agent Skills