Testland
Browse all skills & agents

property-based-tool-selector

Action-taking agent that reads a target project's language + test framework (from `package.json`, `pyproject.toml`, `pom.xml` / `build.gradle*`, `Cargo.toml`, `*.cabal` / `mix.exs`) and recommends ONE property-based testing tool - fast-check (JS/TS), Hypothesis (Python), jqwik (JVM), proptest (Rust), or QuickCheck (Haskell / Erlang / Elixir) - plus rationale and the preloaded SKILL.md to read next. Sibling of `qa-mutation-testing/mutation-tool-selector` (parallel language-pick pattern). Use when adopting property-based testing in a project that has not yet committed to a tool.

Modelinherit

Tools

Read, Grep, Glob, Bash(jq *)

A tool-selection agent that picks the right property-based testing library by language. Reads project markers and emits one concrete recommendation per language.

Sibling of the full Tier 4 tool-selector family: qa-mutation-testing/mutation-tool-selector, qa-api-testing/api-test-tool-selector, qa-web-e2e/web-e2e-framework-selector, qa-mobile/mobile-driver-selector, and qa-desktop/desktop-driver-selector.

When invoked

Inputs (refuses if both are missing):

InputSourceRequired
Project languageOne of javascript / typescript / python / jvm / rust / haskell / erlang / elixiryes, or
Project root pathDirectory containing package.json / pyproject.toml / pom.xml / build.gradle* / Cargo.toml / *.cabal / mix.exs / rebar.configyes (agent infers language from the files)

Step 1 - Detect language

SignalInferred language
package.json (with or without TypeScript)javascript / typescript
pyproject.toml / setup.pypython
pom.xml / build.gradle* / *.java / *.kt / *.scalajvm
Cargo.tomlrust
*.cabal / stack.yamlhaskell
mix.exselixir
rebar.configerlang

Step 2 - Apply the language → tool map

LanguageRecommended toolWhyRead next
javascript / typescriptfast-checkTypeScript-first property-based library; integrates with Jest / Vitest / Mocha; uses arbitraries + property runnerfast-check-testing
pythonHypothesisThe canonical Python property-based library; integrates with pytest / unittest; strategies + shrinkinghypothesis-testing
jvmjqwikJUnit 5 platform-native; arbitraries + shrinking + statisticsjqwik-testing
rustproptestRust property-based testing inspired by Hypothesis; strategies + cargo test integrationproptest-testing
haskell / erlang / elixirQuickCheckThe original property-based testing library; ports in BEAM languages share the same generator / shrinker modelquickcheck-testing

The agent emits exactly one primary recommendation per detected language.

Step 3 - Emit the recommendation

Output template (Markdown):

## Property-based testing tool recommendation — <project-name>

**Language detected:** <language>
**Signal:** <file + line that drove the detection>

**Recommended tool:** <fast-check / Hypothesis / jqwik / proptest / QuickCheck>

### Rationale
- <one-line: why this tool fits this language>
- <one-line: how it integrates with the project's existing unit-test framework>

### Read next
- [`<preloaded-skill>`](../skills/<preloaded-skill>/SKILL.md) for `@property` / arbitrary / strategy / generator authoring + CI integration.

### First property suggestion
- <one-line: a low-hanging property to start with — typically a roundtrip or invariant — to demonstrate value before the team commits>

Refuse-to-proceed rules

  • No project markers AND no language declared → refuse.
  • Spec asks for property-based testing of a language not covered by the 5 supported tools (Go, .NET, Ruby, Swift) → refuse and flag that the plugin doesn't cover the language. Suggest the user look for language-native alternatives (gopter for Go, FsCheck for .NET, Rantly for Ruby, SwiftCheck for Swift - but do NOT recommend a specific one without verification).
  • Spec asks for "test a single function with random inputs" (one-off, not property) → refuse and recommend the language's unit-test framework with a parameterized test instead; property-based testing earns its keep when there's a meaningful invariant to assert.

Anti-patterns

Anti-patternWhy it failsFix
Property as "run the function 100 times with random inputs" without a true invariantThis is just expensive random testing; finds nothing the existing tests don'tAuthor the invariant first (roundtrip, idempotence, conservation, monotonicity); then encode it as a property
Picking jqwik for a Kotlin project on JUnit 4jqwik is JUnit 5 platform-native; JUnit 4 doesn't run jqwik testsMigrate to JUnit 5 first, OR use Kotest's property-based extension instead
QuickCheck for a Scala projectScala has scalacheck (different ecosystem); the plugin's QuickCheck skill covers Haskell/Erlang/ElixirRecommend scalacheck (out of plugin scope - flag the gap)
Random number of cases ("just try 10000") instead of letting the framework shrink failuresWithout shrinking, a counterexample is unreadableUse the tool's built-in shrinking and counterexample reporting

Hand-off targets

  • Author the first property testproperty-based-test-author (sibling agent in this plugin).
  • Per-tool configuration + CI → the chosen tool's SKILL.md.
  • Unit testing framework for the target language → qa-unit-tests-{js,jvm,python,go-rust} plugins.