pbt
pbt is a property-based testing library for Go that helps you verify program behavior against broad classes of generated inputs instead of a few hand-written test cases.
Why pbt
- Fast integration in existing
testing workflows
- Deterministic reproduction via explicit random seeds
- Configurable run count and generator size growth
- Counterexample shrinking for easier debugging
- Shrink traces, failure classifiers, labels, and coverage buckets
- Deterministic parallel execution with partitioned seeds
- Stateful/model-based testing with command sequences and invariants
- Small, modular package layout for maintainability
Installation
Add the module to your project:
import "git.quad4.io/Go-Libs/pbt/pkg/pbt"
Quick Start
package mypkg_test
import (
"testing"
"git.quad4.io/Go-Libs/pbt/pkg/pbt"
)
func TestStringRoundTrip(t *testing.T) {
property := pbt.ForAll(
"double reverse preserves value",
pbt.StringASCII(0, 64),
func(in string) bool {
return reverse(reverse(in)) == in
},
pbt.WithShrinker[string](pbt.StringShrinker()),
)
pbt.Check(t, property, pbt.WithRuns(1000), pbt.WithSeed(42))
}
For non-testing usage, call pbt.CheckResult and inspect the returned result.
Package Layout
pkg/pbt: public API for generators, properties, shrinking, and execution
cmd/pbt-example: runnable example program
Public API Overview
pbt.ForAll: defines a property from generator + predicate
pbt.Check: executes a property and fails the test on first failure
pbt.CheckResult: executes and returns a structured result
pbt.WithRuns, pbt.WithMaxSize, pbt.WithSeed, pbt.WithTimeout: execution configuration options
pbt.WithParallelism: deterministic partitioned parallel execution
pbt.WithShrinkParallelism: shrink strategy worker tuning
- Built-in generators:
Int, IntRange, Bool, Float64, StringASCII, SliceOf, Map
- Conditional generation:
SuchThat and SuchThatFallback filter source values by predicate
- Higher-order generator combinators:
Tuple2, Tuple3, Product2, OneOf, Frequency, Recursive
- Built-in shrinkers:
IntShrinker, StringShrinker, SliceShrinker
- Failure triage hooks:
WithClassifier, WithLabeler, WithBucketer
- Coverage thresholds:
WithLabelCoverageRules, WithBucketCoverageRules
- Distribution tooling:
AnalyzeDistribution, ValidateDistribution
- Stateful testing:
CheckStateful, CheckStatefulResult, CommandSequence
- Replay fixtures:
SerializeCounterexample, DeserializeCounterexample, Result.ToReplayFixture
- Replay runners:
ReplayFixtureFile, ReplayStatefulFixtureFile
- Hook/event bus:
Hook, HookFuncs, WithHook, WithHooks
- Stateful hook/event bus:
StatefulHook, StatefulHookFuncs, CommandModel.Hooks
Reproducibility
Use pbt.WithSeed to reproduce any failure exactly. The Result and failure message include the seed used for the run.
You can persist failing cases by converting a failing Result into a ReplayFixture and writing it to disk.
Taskfile
This repository includes a Taskfile.yml for common workflows:
task fmt: format code
task vet: static analysis
task lint: run revive linter
task test: run unit tests
task test:cov: run tests with coverage (fails if below 75%)
task ci: run format, vet, lint, and tests
Status
This library is structured for production use and intended to grow with additional generators, domain-specific shrinkers, and richer reporting over time.