Skip to content
Back to skills

Coding

ASecurity

Property-based testing with Python Hypothesis — find invariants, write @given strategies, and model stateful systems with RuleBasedStateMachine.

  • 23 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 14, 2026
ai-agentspythonrustgorailstestingapidatabasesecurity

Works with

  • api

Security analysis

A100/100

Pro scans all 21 files and shows the line behind each finding

Scanned October 14, 2026

npx -y skills add andreibesleaga/GABBE --skill coding --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Coding?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Coding
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/andreibesleaga-coding-3f20fab8/badge)](https://www.skillsdirectory.com/skills/andreibesleaga-coding-3f20fab8)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: pbt-strategy
description: Property-based testing with Python Hypothesis — find invariants, write @given strategies, and model stateful systems with RuleBasedStateMachine.
triggers: [write property based tests, find invariants for testing, use hypothesis given strategies, build a rulebasedstatemachine, fuzz json against a schema, shrink to a minimal counterexample]
tags: [coding, testing, hypothesis, property-based-testing, python]
core: false
context_cost: medium
---
# Property-Based Testing Strategy (Hypothesis)

## Goal
Stop hand-picking a few example inputs and instead state the *properties* that must hold for
*all* inputs, then let Hypothesis generate hundreds of diverse cases to attack them. A
property-based test asserts an invariant ("the output is always sorted", "decode(encode(x))
== x") rather than a single example. When it finds a failure, Hypothesis *shrinks* the
counterexample to the smallest input that still breaks the property, handing you a minimal
reproduction. The output of this skill is a **property test plan**: the invariants you will
check, the strategies that generate inputs for them, and — for stateful systems — the state
machine that drives them. Be clear from the start: PBT *samples* the input space to raise
confidence; it does not enumerate it and does not prove correctness.

## Steps
1. **Find the invariants.** Look for properties that hold regardless of the specific input. The
   common families:
   - **Round-trip**: `decode(encode(x)) == x`, `parse(serialize(x)) == x`.
   - **Idempotence**: `f(f(x)) == f(x)` (normalize, dedupe, clamp).
   - **Oracle/equivalence**: a slow-but-obviously-correct reference agrees with the optimized
     implementation; or two code paths that must agree.
   - **Invariant preservation**: an operation never violates a structural rule (a balanced tree
     stays balanced; a total never goes negative; output length never exceeds input).
   - **Metamorphic relations** when there is no oracle for the absolute output — delegate those
     to `metamorphic-testing.skill`.
2. **Write the `@given` strategies.** Generate inputs with Hypothesis strategies
   (`integers()`, `text()`, `lists()`, `dictionaries()`, `builds()`, `composite`). Constrain to
   the *valid* domain with `.filter()` sparingly and `.map()`/`assume()` so generation stays
   efficient — over-filtering makes Hypothesis give up. Compose custom strategies with
   `@composite` for domain objects. Keep each test focused on one invariant.
3. **Fuzz structured data against its schema.** For JSON APIs and configs, use
   `hypothesis-jsonschema`'s `from_schema()` to generate inputs that conform to a JSON Schema,
   then assert your handler never crashes and always returns schema-valid output. This catches
   the edge cases hand-written fixtures miss (empty arrays, unicode, boundary numbers, missing
   optional fields).
4. **Model stateful systems with `RuleBasedStateMachine`.** When behavior depends on a sequence
   of operations (a cache, a queue, a connection pool, a small DB), subclass
   `RuleBasedStateMachine` and let Hypothesis generate *sequences* of actions:
   - `@initialize` seeds starting state once per run.
   - `@rule` defines an action; Hypothesis picks rules and arguments to build random valid
     sequences.
   - `Bundle` holds values produced by one rule (e.g. a created handle) to feed as input to
     later rules, so generated sequences are realistic.
   - `@precondition` gates a rule so it only fires in valid states.
   - `@invariant` is checked after *every* step — the core safety property that must always hold.
   Run it as a normal test; Hypothesis searches for an action sequence that breaks an invariant.
5. **Use shrinking and the example database.** On failure, let Hypothesis shrink to the minimal
   counterexample and read it as your bug report. Pin a found failure with `@example(...)` so it
   becomes a permanent regression case. Keep Hypothesis's example database in CI so previously
   failing inputs are replayed first.
6. **Tune effort honestly.** Set `max_examples` and `deadline` for the time budget; more examples
   = more confidence, never certainty. In CI, raise `max_examples` for critical properties and
   use `derandomize`/a fixed seed only when you need reproducible runs (knowing it narrows the
   search).

## Constraints
- PBT **samples** the input space and **raises confidence**; it does **NOT prove correctness**.
  Unlike formal methods (model checking, proof assistants) which reason over *all* states, a
  passing property test means "no counterexample was found in N sampled cases." State this limit
  in the plan and never claim a property is "proven."
- A property is only as good as its strategy: if the generator never produces the bad input, the
  bug hides. Check the strategy actually covers the domain (use `target()`/coverage if unsure).
- Over-constrained strategies (heavy `.filter()`/`assume()`) cause Hypothesis to abandon
  generation; build valid data directly with `@composite` instead.
- Flaky properties (depending on time, randomness, ordering of external systems) produce
  non-reproducing failures; make the system-under-test deterministic for the test or inject seams.
- Stateful tests grow expensive fast; keep the rule set minimal and the invariant sharp.

## Output Format
Produce a **property test plan** containing:
- The list of invariants, each tagged by family (round-trip / idempotence / oracle /
  invariant-preservation / metamorphic-handoff).
- For each invariant: the Hypothesis strategy (or `from_schema` reference) that generates its
  inputs, and the assertion.
- For stateful components: the `RuleBasedStateMachine` design — rules, bundles, preconditions,
  initialize, and the `@invariant`(s).
- The effort settings (`max_examples`, `deadline`) and any pinned `@example` regression cases.
- An explicit honesty note: the suite samples inputs and raises confidence; it does not prove
  correctness. Cross-reference `metamorphic-testing.skill` for oracle-free relations.

## Security & Guardrails

### 1. Skill Security
- **Risk**: A green property suite is reported as a correctness proof, giving false assurance for
  safety- or security-critical code. Mitigation: every report MUST state PBT samples and does not
  prove; the agent MUST NOT use "property passed" to mean "cannot fail," and MUST recommend formal
  methods where a real proof is required.
- **Risk**: A weak or over-filtered strategy never generates the dangerous input, so the test
  passes vacuously. Mitigation: the agent MUST sanity-check coverage of the strategy (it produces
  edge/boundary/empty/unicode values) and flag any property whose generator cannot reach the
  failure region as low-value.

### 2. System Integration Security
- **Risk**: A stateful or schema-fuzzing test executes real side effects (writes a real DB,
  calls a paid/external API, mutates shared state) and corrupts data or runs up cost. Mitigation:
  run PBT against isolated fixtures, in-memory/transactional fakes, or sandboxes; never point
  generators at production resources, and bound `max_examples` to control blast radius and spend.
- **Risk**: `hypothesis-jsonschema` generates pathological payloads (huge strings, deep nesting)
  that exhaust memory or hang the handler. Mitigation: set `deadline`/size limits in strategies
  and treat resource exhaustion as a finding to fix (input validation), not a test to silence.

### 3. LLM & Agent Guardrails
- **Risk**: The agent invents a plausible but false invariant (asserting a property the spec
  never required), turning the test green while masking real behavior. Mitigation: each invariant
  MUST trace to a stated requirement or contract; the agent MUST mark agent-derived invariants as
  proposed and ask for confirmation before trusting them.
- **Risk**: The agent hallucinates Hypothesis API surface (non-existent strategies or state-machine
  decorators) that errors or silently skips. Mitigation: emit only real, current Hypothesis APIs
  (`@given`, `@rule`, `@initialize`, `@precondition`, `@invariant`, `Bundle`, `from_schema`); the
  agent MUST verify the test actually runs and can fail before presenting it as coverage.

Files in this skill

  • agent-trajectory-eval.skill.md5.7 KB
  • artisan-commands.skill.md3.7 KB
  • browser-tdd.skill.md7 KB
  • chaos-fault-injection.skill.md8.1 KB
  • ci-autofix.skill.md4.2 KB
  • clean-coder.skill.md4.5 KB
  • code-review.skill.md6.1 KB
  • debug.skill.md6.5 KB
  • documentation.skill.md7.3 KB
  • eval-driven-development.skill.md6.9 KB
  • evals/code-review.eval.yaml1 KB
  • excalidraw.skill.md3.7 KB
  • file-processing.skill.md4.3 KB
  • git-workflow.skill.md7.2 KB
  • metamorphic-testing.skill.md7.8 KB
  • mobile-dev.skill.md4.2 KB
  • nodejs-expert.skill.md1.6 KB
  • output-validation.skill.md5.4 KB
  • pbt-strategy.skill.md8 KB
  • performant-ai.skill.md3.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.