specta#
import "github.com/james-w/specta"Package specta provides deterministic, concurrency-safe generators of primitive values for use in tests, plus spec-first factory utilities.
Index#
- func AssertThat[T any](t TestingT, actual T, matcher Matcher[T])
- func BuildMatcherStructDiff(typeName string, fieldValues map[string]any, fieldResults map[string]*MatchResult) string
- func DeterministicUUIDFromInt(i uint64) uuid.UUID
- func Draw[V any](t *T, gen Gen[V], label string) V
- func Property(t TestingT, check func(*T), opts …PropertyOption)
- func RequireThat[T any](t TestingT, actual T, matcher Matcher[T])
- type BuildWithSpec
- type ChoiceGenerator
- func Choice[T any](gens …Gen[T]) *ChoiceGenerator[T]
- func (g *ChoiceGenerator[T]) Draw(d conjecture.DataSource) (T, error)
- func (g *ChoiceGenerator[T]) Filter(pred func(T) bool) Gen[T]
- func (g *ChoiceGenerator[T]) Or(gen Gen[T]) *ChoiceGenerator[T]
- func (g *ChoiceGenerator[T]) OrWeighted(gen Gen[T], weight int) *ChoiceGenerator[T]
- func (g *ChoiceGenerator[T]) String() string
- type DataSource
- type Gen
- func Bool() Gen[bool]
- func Build[T any](label string, constructor func(d DataSource) (T, error)) Gen[T]
- func Bytes() Gen[[]byte]
- func BytesLen(minLen, maxLen int) Gen[[]byte]
- func Duration() Gen[time.Duration]
- func Email() Gen[string]
- func Float64(min, max float64) Gen[float64]
- func FromSpecGen[T any, S any](build BuildWithSpec[T, S], newSpec func() S, opts …Opt[S]) Gen[T]
- func Just[T any](value T) Gen[T]
- func Map[T, U any](gen Gen[T], fn func(T) U) Gen[U]
- func Optional[T any](gen Gen[T], presentProbability …float64) Gen[*T]
- func Pair[A, B any](ga Gen[A], gb Gen[B]) Gen[struct { A A B B }]
- func PtrOfGen[T any](gen Gen[T]) Gen[*T]
- func Time() Gen[time.Time]
- func Triple[A, B, C any](ga Gen[A], gb Gen[B], gc Gen[C]) Gen[struct { A A B B C C }]
- func URL() Gen[string]
- func UUID() Gen[string]
- func UUIDString() Gen[string]
- type Generator
- type IntGenerator
- func Int() *IntGenerator
- func (g *IntGenerator) Draw(d conjecture.DataSource) (int64, error)
- func (g *IntGenerator) Filter(pred func(int64) bool) Gen[int64]
- func (g *IntGenerator) Max(max int64) *IntGenerator
- func (g *IntGenerator) Min(min int64) *IntGenerator
- func (g *IntGenerator) Negative() *IntGenerator
- func (g *IntGenerator) NonNegative() *IntGenerator
- func (g *IntGenerator) Positive() *IntGenerator
- func (g *IntGenerator) Range(min, max int64) *IntGenerator
- func (g *IntGenerator) String() string
- type Interval
- type MapGenerator
- func MapOf[K comparable, V any](keyGen Gen[K], valueGen Gen[V]) *MapGenerator[K, V]
- func (g *MapGenerator[K, V]) Draw(d conjecture.DataSource) (map[K]V, error)
- func (g *MapGenerator[K, V]) Filter(pred func(map[K]V) bool) Gen[map[K]V]
- func (g *MapGenerator[K, V]) MaxLen(n int) *MapGenerator[K, V]
- func (g *MapGenerator[K, V]) MinLen(n int) *MapGenerator[K, V]
- func (g *MapGenerator[K, V]) NonEmpty() *MapGenerator[K, V]
- func (g *MapGenerator[K, V]) String() string
- type MatchResult
- type Matcher
- func After(expected time.Time) Matcher[time.Time]
- func AllOf[T any](matchers …Matcher[T]) Matcher[T]
- func Any[T any](matcher Matcher[T]) Matcher[[]T]
- func AnyOf[T any](matchers …Matcher[T]) Matcher[T]
- func Before(expected time.Time) Matcher[time.Time]
- func Between(start, end time.Time) Matcher[time.Time]
- func Contains(substr string) Matcher[string]
- func ContainsAllElements[T comparable](items …T) Matcher[[]T]
- func ContainsAnyElement[T comparable](items …T) Matcher[[]T]
- func ContainsElement[T comparable](item T) Matcher[[]T]
- func DeepEqual[T any](expected T) Matcher[T]
- func Equal[T comparable](expected T) Matcher[T]
- func ErrorAs[T error](target *T) Matcher[error]
- func ErrorContains(substr string) Matcher[error]
- func ErrorIs(target error) Matcher[error]
- func Every[T any](matcher Matcher[T]) Matcher[[]T]
- func Field[T any, V any](name string, extractor func(T) V, matcher Matcher[V]) Matcher[T]
- func GreaterThan[T interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64 }](threshold T) Matcher[T]
- func GreaterThanOrEqual[T interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64 }](threshold T) Matcher[T]
- func HasEntry[K comparable, V comparable](key K, value V) Matcher[map[K]V]
- func HasKey[K comparable, V any](key K) Matcher[map[K]V]
- func HasPrefix(prefix string) Matcher[string]
- func HasSize[T any](expectedSize int) Matcher[[]T]
- func HasSuffix(suffix string) Matcher[string]
- func HasValue[K comparable, V comparable](value V) Matcher[map[K]V]
- func Is[T comparable](expected T) Matcher[T]
- func IsEmpty[T any]() Matcher[[]T]
- func IsError() Matcher[error]
- func IsFalse() Matcher[bool]
- func IsNil[T any]() Matcher[*T]
- func IsNotEmpty[T any]() Matcher[[]T]
- func IsNotNil[T any]() Matcher[*T]
- func IsTrue() Matcher[bool]
- func IsZero[T any]() Matcher[T]
- func LessThan[T interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64 }](threshold T) Matcher[T]
- func LessThanOrEqual[T interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64 }](threshold T) Matcher[T]
- func MapHasSize[K comparable, V any](expectedSize int) Matcher[map[K]V]
- func MatchesPattern(regex *regexp.Regexp) Matcher[string]
- func MatchesRegex(pattern string) Matcher[string]
- func NoErr() Matcher[error]
- func None[T any](matcher Matcher[T]) Matcher[[]T]
- func Not[T any](matcher Matcher[T]) Matcher[T]
- func PointsTo[T any](matcher Matcher[T]) Matcher[*T]
- func WithinDuration(expected time.Time, delta time.Duration) Matcher[time.Time]
- type MatcherFunc
- type Maybe
- type Opt
- type Primitives
- type PrimitivesGen
- func New(opts …PrimitivesOption) *PrimitivesGen
- func (g *PrimitivesGen) Bool() bool
- func (g *PrimitivesGen) Bytes() []byte
- func (g *PrimitivesGen) BytesN(n int) []byte
- func (g *PrimitivesGen) DrawBits(n int) uint64
- func (g *PrimitivesGen) Duration() time.Duration
- func (g *PrimitivesGen) EndInterval()
- func (g *PrimitivesGen) Float64() float64
- func (g *PrimitivesGen) ID() string
- func (g *PrimitivesGen) Int() int
- func (g *PrimitivesGen) Int64() int64
- func (g *PrimitivesGen) IntN(max int) int
- func (g *PrimitivesGen) IsDeterministic() bool
- func (g *PrimitivesGen) Next() uint64
- func (g *PrimitivesGen) StartInterval(label string)
- func (g *PrimitivesGen) String() string
- func (g *PrimitivesGen) StringWith(prefix string) string
- func (g *PrimitivesGen) Time() time.Time
- func (g *PrimitivesGen) TimeAtOffset(d time.Duration) time.Time
- func (g *PrimitivesGen) UUID() uuid.UUID
- func (g *PrimitivesGen) Uint64() uint64
- func (g *PrimitivesGen) WriteLog(msg string)
- type PrimitivesOption
- type PropertyOption
- type ShrinkBuffer
- func NewShrinkBuffer(data []byte) *ShrinkBuffer
- func (sb *ShrinkBuffer) Data() []byte
- func (sb *ShrinkBuffer) DeleteRange(start, end int) bool
- func (sb *ShrinkBuffer) Len() int
- func (sb *ShrinkBuffer) MinimizeByte(index int, delta byte) bool
- func (sb *ShrinkBuffer) SetByte(index int, value byte) bool
- func (sb *ShrinkBuffer) Swap(i, j int) bool
- type Shrinker
- type SliceGenerator
- func Slice[T any](elem Gen[T]) *SliceGenerator[T]
- func (g *SliceGenerator[T]) Draw(d conjecture.DataSource) ([]T, error)
- func (g *SliceGenerator[T]) Filter(pred func([]T) bool) Gen[[]T]
- func (g *SliceGenerator[T]) Len(n int) *SliceGenerator[T]
- func (g *SliceGenerator[T]) MaxLen(n int) *SliceGenerator[T]
- func (g *SliceGenerator[T]) MinLen(n int) *SliceGenerator[T]
- func (g *SliceGenerator[T]) NonEmpty() *SliceGenerator[T]
- func (g *SliceGenerator[T]) String() string
- type Source
- type SpecFactory
- type StringGenerator
- func String() *StringGenerator
- func (g *StringGenerator) ASCII() *StringGenerator
- func (g *StringGenerator) Alpha() *StringGenerator
- func (g *StringGenerator) AlphaNum() *StringGenerator
- func (g *StringGenerator) Draw(d conjecture.DataSource) (string, error)
- func (g *StringGenerator) ExampleHint(hint string) *StringGenerator
- func (g *StringGenerator) Filter(pred func(string) bool) Gen[string]
- func (g *StringGenerator) Len(n int) *StringGenerator
- func (g *StringGenerator) MaxLen(n int) *StringGenerator
- func (g *StringGenerator) MinLen(n int) *StringGenerator
- func (g *StringGenerator) NonEmpty() *StringGenerator
- func (g *StringGenerator) Prefix(p string) *StringGenerator
- func (g *StringGenerator) Printable() *StringGenerator
- func (g *StringGenerator) String() string
- func (g *StringGenerator) Suffix(s string) *StringGenerator
- type T
- type TestingT
func AssertThat#
func AssertThat[T any](t TestingT, actual T, matcher Matcher[T])AssertThat checks if actual matches the given matcher, failing the test if not.
func BuildMatcherStructDiff#
func BuildMatcherStructDiff(typeName string, fieldValues map[string]any, fieldResults map[string]*MatchResult) stringBuildMatcherStructDiff creates a structured diff output for generated matchers. It shows matched (✓), failed (✗), and unchecked (~) fields with proper indentation.
func DeterministicUUIDFromInt#
func DeterministicUUIDFromInt(i uint64) uuid.UUIDfunc Draw#
func Draw[V any](t *T, gen Gen[V], label string) VDraw draws a labeled value from a generator and automatically tracks it for error reporting. Using labels improves error messages by showing variable names in failures.
Example:
xs := specta.Draw(t, specta.Slice(specta.Int().Range(0, 100)), "xs")The generated value will automatically appear in error messages when the property fails.
Error handling: - Programming errors (invalid constraints, frozen data) panic with clear messages - Filtering errors (overrun during replay, assumption failures) trigger skipTest to skip the iteration
func Property#
func Property(t TestingT, check func(*T), opts ...PropertyOption)Property runs a property-based test. It executes the check function multiple times with randomly generated inputs. If a failure is detected, it attempts to shrink the input to a minimal failing case.
Example:
Property(t, func(t *specta.T) {
x := Int().Draw(t, "x")
y := Int().Draw(t, "y")
AssertThat(t, x+y, Equal(y+x))
})func RequireThat#
func RequireThat[T any](t TestingT, actual T, matcher Matcher[T])RequireThat checks if actual matches the given matcher, stopping the test immediately if not. Unlike AssertThat which continues after failures, RequireThat calls t.Fatalf() to halt execution. This is useful for preconditions where subsequent code would panic or produce misleading errors.
Example:
// Guard condition - user must not be nil for subsequent assertions
RequireThat(t, user, NotNil())
AssertThat(t, user.Name, Equal("Alice")) // Safe - user is guaranteed non-niltype BuildWithSpec#
BuildWithSpec constructs T from Source plus the collected spec S.
type BuildWithSpec[T any, S any] func(s Source, spec S) Ttype ChoiceGenerator#
ChoiceGenerator provides fluent API for choosing between alternative generators
type ChoiceGenerator[T any] struct {
// contains filtered or unexported fields
}func Choice#
func Choice[T any](gens ...Gen[T]) *ChoiceGenerator[T]Choice creates a generator that chooses uniformly from the given alternatives. Earlier alternatives are preferred during shrinking.
Example:
gen := specta.Choice(
specta.Int().Range(1, 10),
specta.Int().Range(100, 200),
)func (*ChoiceGenerator[T]) Draw#
func (g *ChoiceGenerator[T]) Draw(d conjecture.DataSource) (T, error)Draw implements Gen[T]
func (*ChoiceGenerator[T]) Filter#
func (g *ChoiceGenerator[T]) Filter(pred func(T) bool) Gen[T]Filter returns a generator that only produces values satisfying the predicate
func (*ChoiceGenerator[T]) Or#
func (g *ChoiceGenerator[T]) Or(gen Gen[T]) *ChoiceGenerator[T]Or adds another alternative with equal weight
func (*ChoiceGenerator[T]) OrWeighted#
func (g *ChoiceGenerator[T]) OrWeighted(gen Gen[T], weight int) *ChoiceGenerator[T]OrWeighted adds an alternative with a specific weight. The first call to OrWeighted converts to weighted mode (existing alternatives get weight 1).
Example:
// 90% small numbers, 10% large numbers
gen := specta.Choice(specta.Int().Range(1, 10)).
OrWeighted(specta.Int().Range(100, 200), 1)func (*ChoiceGenerator[T]) String#
func (g *ChoiceGenerator[T]) String() stringString implements Gen[T]
type DataSource#
DataSource is re-exported from conjecture for user convenience. Users can write custom generators without importing conjecture package.
type DataSource = conjecture.DataSourcetype Gen#
Gen is an alias for conjecture.Gen for convenience
type Gen[T any] = conjecture.Gen[T]func Bool#
func Bool() Gen[bool]Bool creates a boolean generator
func Build#
func Build[T any](label string, constructor func(d DataSource) (T, error)) Gen[T]Build creates a new generator from a constructor function. Re-exported from conjecture for user convenience.
func Bytes#
func Bytes() Gen[[]byte]Bytes creates a []byte generator
func BytesLen#
func BytesLen(minLen, maxLen int) Gen[[]byte]BytesLen creates a []byte generator with specific length
func Duration#
func Duration() Gen[time.Duration]Duration creates a time.Duration generator
func Email#
func Email() Gen[string]Email returns a generator for email addresses
func Float64#
func Float64(min, max float64) Gen[float64]Float64 creates a float64 generator for [min, max]
func FromSpecGen#
func FromSpecGen[T any, S any](build BuildWithSpec[T, S], newSpec func() S, opts ...Opt[S]) Gen[T]FromSpecGen creates a Gen[T] from a BuildWithSpec function and spec options. This is used for generating nested custom types.
func Just#
func Just[T any](value T) Gen[T]Just creates a generator that always returns the same literal value. Re-exported from conjecture for user convenience.
func Map#
func Map[T, U any](gen Gen[T], fn func(T) U) Gen[U]Map transforms a generator’s output using a mapping function. Re-exported from conjecture for user convenience.
func Optional#
func Optional[T any](gen Gen[T], presentProbability ...float64) Gen[*T]Optional returns a generator that produces either a value or nil (pointer with optional probability). Returns a pointer: nil for no value, *T for a value.
By default, generates present values 80% of the time (matching conjecture.Optional). Pass a custom probability to override:
specta.Optional(gen) // 80% present
specta.Optional(gen, 0.5) // 50% present
specta.Optional(gen, 0.2) // 20% present (rare)
specta.Optional(gen, 0.95) // 95% present (common)func Pair#
func Pair[A, B any](ga Gen[A], gb Gen[B]) Gen[struct {
A A
B B
}]Pair generates a tuple of two values. Returns a struct with fields A and B.
Example:
coords := specta.Pair(
specta.Float64(-180, 180), // longitude
specta.Float64(-90, 90), // latitude
)
pair := specta.Draw(pt, coords, "coords")
lon := pair.A // float64
lat := pair.B // float64func PtrOfGen#
func PtrOfGen[T any](gen Gen[T]) Gen[*T]PtrOfGen creates a Gen[*T] from a Gen[T]. This is used for generating pointers to custom types.
func Time#
func Time() Gen[time.Time]Time creates a time.Time generator
func Triple#
func Triple[A, B, C any](ga Gen[A], gb Gen[B], gc Gen[C]) Gen[struct {
A A
B B
C C
}]Triple generates a tuple of three values. Returns a struct with fields A, B, and C.
Example:
coords3d := specta.Triple(
specta.Float64(-180, 180), // longitude
specta.Float64(-90, 90), // latitude
specta.Float64(0, 10000), // altitude
)func URL#
func URL() Gen[string]URL returns a generator for URLs
func UUID#
func UUID() Gen[string]UUID creates a UUID string generator
func UUIDString#
func UUIDString() Gen[string]UUIDString returns a generator for UUID strings (alias for UUID)
type Generator#
Generator is an alias for Gen[T] - used in generated code for convenience
type Generator[T any] = Gen[T]type IntGenerator#
IntGenerator provides a fluent API for building integer generators
type IntGenerator struct {
// contains filtered or unexported fields
}func Int#
func Int() *IntGeneratorInt creates an integer generator with optional constraints
func (*IntGenerator) Draw#
func (g *IntGenerator) Draw(d conjecture.DataSource) (int64, error)Draw implements Gen[int64]
func (*IntGenerator) Filter#
func (g *IntGenerator) Filter(pred func(int64) bool) Gen[int64]Filter returns a generator that only produces integers satisfying the predicate
func (*IntGenerator) Max#
func (g *IntGenerator) Max(max int64) *IntGeneratorMax sets the maximum value (inclusive)
func (*IntGenerator) Min#
func (g *IntGenerator) Min(min int64) *IntGeneratorMin sets the minimum value (inclusive)
func (*IntGenerator) Negative#
func (g *IntGenerator) Negative() *IntGeneratorNegative constrains to negative integers (< 0)
func (*IntGenerator) NonNegative#
func (g *IntGenerator) NonNegative() *IntGeneratorNonNegative constrains to non-negative integers (>= 0)
func (*IntGenerator) Positive#
func (g *IntGenerator) Positive() *IntGeneratorPositive constrains to positive integers (> 0)
func (*IntGenerator) Range#
func (g *IntGenerator) Range(min, max int64) *IntGeneratorRange constrains the integer to [min, max]
func (*IntGenerator) String#
func (g *IntGenerator) String() stringString implements Gen[int64]
type Interval#
Interval represents a contiguous range of bytes drawn from the random source. Intervals are used by the shrinker to understand the structure of generated values and perform intelligent minimization (e.g., deleting entire values, reordering).
type Interval struct {
// Start is the byte offset where this interval begins in the data stream
Start int
// End is the byte offset where this interval ends (exclusive)
End int
// Label is a human-readable description of what this interval represents
// (e.g., "x", "list_length", "element_0")
Label string
}type MapGenerator#
MapGenerator provides fluent API for map generation
type MapGenerator[K comparable, V any] struct {
// contains filtered or unexported fields
}func MapOf#
func MapOf[K comparable, V any](keyGen Gen[K], valueGen Gen[V]) *MapGenerator[K, V]MapOf creates a map generator from key and value generators.
func (*MapGenerator[K, V]) Draw#
func (g *MapGenerator[K, V]) Draw(d conjecture.DataSource) (map[K]V, error)Draw implements Gen[map[K]V]
func (*MapGenerator[K, V]) Filter#
func (g *MapGenerator[K, V]) Filter(pred func(map[K]V) bool) Gen[map[K]V]Filter returns a generator that only produces maps satisfying the predicate
func (*MapGenerator[K, V]) MaxLen#
func (g *MapGenerator[K, V]) MaxLen(n int) *MapGenerator[K, V]MaxLen sets maximum map size
func (*MapGenerator[K, V]) MinLen#
func (g *MapGenerator[K, V]) MinLen(n int) *MapGenerator[K, V]MinLen sets minimum map size
func (*MapGenerator[K, V]) NonEmpty#
func (g *MapGenerator[K, V]) NonEmpty() *MapGenerator[K, V]NonEmpty ensures map has at least one entry
func (*MapGenerator[K, V]) String#
func (g *MapGenerator[K, V]) String() stringString implements Gen[map[K]V]
type MatchResult#
MatchResult represents the result of a match operation.
type MatchResult struct {
Matched bool // Whether the match succeeded
Message string // Human-readable description of the failure
Details []string // Additional details about what didn't match
Expected any // Expected value (optional, for better error messages)
Actual any // Actual value (optional, for better error messages)
Path string // Field path for nested failures (e.g., "User.Address.City")
}type Matcher#
Matcher defines an interface for matching values of type T.
type Matcher[T any] interface {
Matches(actual T) MatchResult
}func After#
func After(expected time.Time) Matcher[time.Time]After creates a matcher that checks if a time is after the expected time.
func AllOf#
func AllOf[T any](matchers ...Matcher[T]) Matcher[T]AllOf creates a matcher that requires all sub-matchers to match.
func Any#
func Any[T any](matcher Matcher[T]) Matcher[[]T]Any creates a matcher that checks if at least one element in a slice matches the given matcher.
func AnyOf#
func AnyOf[T any](matchers ...Matcher[T]) Matcher[T]AnyOf creates a matcher that requires at least one sub-matcher to match.
func Before#
func Before(expected time.Time) Matcher[time.Time]Before creates a matcher that checks if a time is before the expected time.
func Between#
func Between(start, end time.Time) Matcher[time.Time]Between creates a matcher that checks if a time is between start and end (inclusive).
func Contains#
func Contains(substr string) Matcher[string]Contains checks if a string contains a substring.
func ContainsAllElements#
func ContainsAllElements[T comparable](items ...T) Matcher[[]T]ContainsAllElements creates a matcher that checks if a slice contains all expected items.
func ContainsAnyElement#
func ContainsAnyElement[T comparable](items ...T) Matcher[[]T]ContainsAnyElement creates a matcher that checks if a slice contains at least one of the expected items.
func ContainsElement#
func ContainsElement[T comparable](item T) Matcher[[]T]ContainsElement creates a matcher that checks if a slice contains the expected item.
func DeepEqual#
func DeepEqual[T any](expected T) Matcher[T]DeepEqual creates a matcher that uses reflect.DeepEqual for comparison. This works with any type, including slices, maps, and other non-comparable types.
func Equal#
func Equal[T comparable](expected T) Matcher[T]Equal creates a matcher that checks for exact equality.
func ErrorAs#
func ErrorAs[T error](target *T) Matcher[error]ErrorAs creates a matcher that checks if an error can be assigned to the target type using errors.As. The target parameter must be a pointer to an error type.
func ErrorContains#
func ErrorContains(substr string) Matcher[error]ErrorContains creates a matcher that checks if an error’s message contains the expected substring. Returns false if the error is nil.
func ErrorIs#
func ErrorIs(target error) Matcher[error]ErrorIs creates a matcher that checks if an error matches the target error using errors.Is. This checks the error chain, not just equality.
func Every#
func Every[T any](matcher Matcher[T]) Matcher[[]T]Every creates a matcher that checks if all elements in a slice match the given matcher.
func Field#
func Field[T any, V any](name string, extractor func(T) V, matcher Matcher[V]) Matcher[T]Field creates a matcher that extracts a value from T using an extractor function, then applies a matcher to the extracted value. This is useful for: - Matching on computed/derived values - Matching on values from getter methods - Matching on unexported fields (via getters)
Example:
Field("balance * 2", func(acc BankAccount) int {
return acc.GetBalance() * 2
}, Equal(2000))func GreaterThan#
func GreaterThan[T interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64
}](threshold T) Matcher[T]GreaterThan creates a matcher for numeric types.
func GreaterThanOrEqual#
func GreaterThanOrEqual[T interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64
}](threshold T) Matcher[T]GreaterThanOrEqual creates a matcher for numeric types.
func HasEntry#
func HasEntry[K comparable, V comparable](key K, value V) Matcher[map[K]V]HasEntry creates a matcher that checks if a map contains the specified key-value pair.
func HasKey#
func HasKey[K comparable, V any](key K) Matcher[map[K]V]HasKey creates a matcher that checks if a map contains the specified key.
func HasPrefix#
func HasPrefix(prefix string) Matcher[string]HasPrefix checks if a string has a given prefix.
func HasSize#
func HasSize[T any](expectedSize int) Matcher[[]T]HasSize creates a matcher that checks if a slice has exactly the expected size.
func HasSuffix#
func HasSuffix(suffix string) Matcher[string]HasSuffix checks if a string has a given suffix.
func HasValue#
func HasValue[K comparable, V comparable](value V) Matcher[map[K]V]HasValue creates a matcher that checks if a map contains the specified value.
func Is#
func Is[T comparable](expected T) Matcher[T]Is is an alias for Equal for more readable assertions.
func IsEmpty#
func IsEmpty[T any]() Matcher[[]T]IsEmpty creates a matcher that checks if a slice is empty.
func IsError#
func IsError() Matcher[error]IsError creates a matcher that checks if an error is non-nil.
func IsFalse#
func IsFalse() Matcher[bool]IsFalse checks if a boolean is false.
func IsNil#
func IsNil[T any]() Matcher[*T]IsNil creates a matcher that checks if a pointer is nil.
func IsNotEmpty#
func IsNotEmpty[T any]() Matcher[[]T]IsNotEmpty creates a matcher that checks if a slice has at least one element.
func IsNotNil#
func IsNotNil[T any]() Matcher[*T]IsNotNil creates a matcher that checks if a pointer is not nil.
func IsTrue#
func IsTrue() Matcher[bool]IsTrue checks if a boolean is true.
func IsZero#
func IsZero[T any]() Matcher[T]IsZero checks if a value is the zero value for its type.
func LessThan#
func LessThan[T interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64
}](threshold T) Matcher[T]LessThan creates a matcher for numeric types.
func LessThanOrEqual#
func LessThanOrEqual[T interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64
}](threshold T) Matcher[T]LessThanOrEqual creates a matcher for numeric types.
func MapHasSize#
func MapHasSize[K comparable, V any](expectedSize int) Matcher[map[K]V]MapHasSize creates a matcher that checks if a map has exactly the expected size.
func MatchesPattern#
func MatchesPattern(regex *regexp.Regexp) Matcher[string]MatchesPattern creates a matcher that checks if a string matches the given compiled regex.
func MatchesRegex#
func MatchesRegex(pattern string) Matcher[string]MatchesRegex creates a matcher that checks if a string matches the given regex pattern. The pattern is compiled internally; if compilation fails, the match will fail.
func NoErr#
func NoErr() Matcher[error]NoErr creates a matcher that checks if an error is nil. This is a convenience matcher for the common case of asserting no error occurred.
func None#
func None[T any](matcher Matcher[T]) Matcher[[]T]None creates a matcher that checks if no elements in a slice match the given matcher.
func Not#
func Not[T any](matcher Matcher[T]) Matcher[T]Not negates a matcher.
func PointsTo#
func PointsTo[T any](matcher Matcher[T]) Matcher[*T]PointsTo creates a matcher that checks if a pointer points to a value matching the given matcher. Returns false if the pointer is nil.
func WithinDuration#
func WithinDuration(expected time.Time, delta time.Duration) Matcher[time.Time]WithinDuration creates a matcher that checks if a time is within delta duration of the expected time. This is useful for fuzzy time comparisons where exact equality isn’t practical.
type MatcherFunc#
MatcherFunc is a function that implements the Matcher interface.
type MatcherFunc[T any] func(T) MatchResultfunc (MatcherFunc[T]) Matches#
func (f MatcherFunc[T]) Matches(actual T) MatchResulttype Maybe#
Maybe holds an optional Gen.
type Maybe[V any] struct {
// contains filtered or unexported fields
}func Some#
func Some[V any](gen Gen[V]) Maybe[V]Some creates a Maybe with a generator.
func (Maybe[V]) GetValue#
func (m Maybe[V]) GetValue(s Source, label string) VGetValue draws the value from this Maybe’s generator. Panics if the Maybe is not set. Use IsSet() to check first.
func (Maybe[V]) GetWithGenerator#
func (m Maybe[V]) GetWithGenerator(s Source, label string, defGen Gen[V]) VGetWithGenerator returns the set value if present, otherwise draws from the default generator. This is used by generated factory code to support composable generator defaults. The Source parameter can be either *PrimitivesGen (deterministic) or *conjecture.ConjectureData (property testing).
func (Maybe[V]) IsSet#
func (m Maybe[V]) IsSet() boolIsSet returns true if this Maybe has a value.
type Opt#
Opt applies to a spec S (not the final instance).
type Opt[S any] func(*S)func Compose#
func Compose[S any](opts ...Opt[S]) Opt[S]func SetLit#
func SetLit[S any, V any](assign func(*S, Maybe[V]), v V) Opt[S]Spec option composition helpers.
func SetWith#
func SetWith[S any, V any](assign func(*S, Maybe[V]), gen Gen[V]) Opt[S]type Primitives#
type Primitives interface {
Next() uint64
Bool() bool
Int() int
IntN(max int) int
Int64() int64
Uint64() uint64
Float64() float64
String() string
StringWith(prefix string) string
Bytes() []byte
BytesN(n int) []byte
Time() time.Time
TimeAtOffset(d time.Duration) time.Time
Duration() time.Duration
ID() string
UUID() uuid.UUID
}type PrimitivesGen#
PrimitivesGen is a deterministic generator for factory test data
type PrimitivesGen struct {
// contains filtered or unexported fields
}func New#
func New(opts ...PrimitivesOption) *PrimitivesGenfunc (*PrimitivesGen) Bool#
func (g *PrimitivesGen) Bool() boolBool always returns false for deterministic, minimal test data generation. This is intentional - Gen is for factories, not property testing. For random booleans, use PropertyPrimitives.
func (*PrimitivesGen) Bytes#
func (g *PrimitivesGen) Bytes() []bytefunc (*PrimitivesGen) BytesN#
func (g *PrimitivesGen) BytesN(n int) []bytefunc (*PrimitivesGen) DrawBits#
func (g *PrimitivesGen) DrawBits(n int) uint64DrawBits implements Source interface. Returns bits from the counter for deterministic, predictable generation.
func (*PrimitivesGen) Duration#
func (g *PrimitivesGen) Duration() time.Durationfunc (*PrimitivesGen) EndInterval#
func (g *PrimitivesGen) EndInterval()EndInterval implements Source interface. No-op for Gen since it doesn’t track intervals (only used for property testing).
func (*PrimitivesGen) Float64#
func (g *PrimitivesGen) Float64() float64func (*PrimitivesGen) ID#
func (g *PrimitivesGen) ID() stringfunc (*PrimitivesGen) Int#
func (g *PrimitivesGen) Int() intfunc (*PrimitivesGen) Int64#
func (g *PrimitivesGen) Int64() int64func (*PrimitivesGen) IntN#
func (g *PrimitivesGen) IntN(max int) intfunc (*PrimitivesGen) IsDeterministic#
func (g *PrimitivesGen) IsDeterministic() boolIsDeterministic implements Source interface. Returns true because Gen produces predictable, friendly values.
func (*PrimitivesGen) Next#
func (g *PrimitivesGen) Next() uint64func (*PrimitivesGen) StartInterval#
func (g *PrimitivesGen) StartInterval(label string)StartInterval implements Source interface. No-op for Gen since it doesn’t track intervals (only used for property testing).
func (*PrimitivesGen) String#
func (g *PrimitivesGen) String() stringfunc (*PrimitivesGen) StringWith#
func (g *PrimitivesGen) StringWith(prefix string) stringfunc (*PrimitivesGen) Time#
func (g *PrimitivesGen) Time() time.Timefunc (*PrimitivesGen) TimeAtOffset#
func (g *PrimitivesGen) TimeAtOffset(d time.Duration) time.Timefunc (*PrimitivesGen) UUID#
func (g *PrimitivesGen) UUID() uuid.UUIDfunc (*PrimitivesGen) Uint64#
func (g *PrimitivesGen) Uint64() uint64func (*PrimitivesGen) WriteLog#
func (g *PrimitivesGen) WriteLog(msg string)WriteLog implements Source interface. Appends to the log if logging is enabled.
type PrimitivesOption#
type PrimitivesOption func(*PrimitivesGen)func WithBaseTime#
func WithBaseTime(t time.Time) PrimitivesOptionfunc WithPrefix#
func WithPrefix(p string) PrimitivesOptionfunc WithStart#
func WithStart(start uint64) PrimitivesOptionfunc WithTimeStep#
func WithTimeStep(step time.Duration) PrimitivesOptiontype PropertyOption#
PropertyOption configures property testing behavior.
type PropertyOption func(*propertyConfig)func MaxShrinks#
func MaxShrinks(n int) PropertyOptionMaxShrinks sets the maximum number of shrinking attempts. Default is 1000.
func MaxTests#
func MaxTests(n int) PropertyOptionMaxTests sets the maximum number of test iterations to run. Default is 100.
func Seed#
func Seed(seed int64) PropertyOptionSeed sets the random seed for deterministic test generation. This is primarily used to reproduce failures. Default is based on the current time.
type ShrinkBuffer#
ShrinkBuffer is a mutable buffer for trying shrinking modifications. It wraps a byte slice and provides operations for deletion, minimization, and reordering.
type ShrinkBuffer struct {
// contains filtered or unexported fields
}func NewShrinkBuffer#
func NewShrinkBuffer(data []byte) *ShrinkBufferNewShrinkBuffer creates a new shrink buffer from the given data.
func (*ShrinkBuffer) Data#
func (sb *ShrinkBuffer) Data() []byteData returns a copy of the current buffer contents.
func (*ShrinkBuffer) DeleteRange#
func (sb *ShrinkBuffer) DeleteRange(start, end int) boolDeleteRange deletes bytes from [start, end). Returns true if the deletion was successful, false if indices are invalid.
func (*ShrinkBuffer) Len#
func (sb *ShrinkBuffer) Len() intLen returns the length of the buffer.
func (*ShrinkBuffer) MinimizeByte#
func (sb *ShrinkBuffer) MinimizeByte(index int, delta byte) boolMinimizeByte attempts to reduce the value at index by delta. Returns true if successful, false if the result would be negative or index is invalid.
func (*ShrinkBuffer) SetByte#
func (sb *ShrinkBuffer) SetByte(index int, value byte) boolSetByte sets the byte at index to value. Returns true if successful, false if index is invalid.
func (*ShrinkBuffer) Swap#
func (sb *ShrinkBuffer) Swap(i, j int) boolSwap swaps the bytes at indices i and j. Returns true if successful, false if indices are invalid.
type Shrinker#
Shrinker orchestrates the shrinking process using multiple passes. It maintains the best (shortest/simplest) failing example found so far.
type Shrinker struct {
// contains filtered or unexported fields
}func NewShrinker#
func NewShrinker(data []byte, intervals []Interval, testFunc func([]byte) bool) *ShrinkerNewShrinker creates a new shrinker for the given failing test case. testFunc should return true if the test still fails for the given byte stream.
func (*Shrinker) Calls#
func (s *Shrinker) Calls() intCalls returns the number of test executions performed during shrinking.
func (*Shrinker) Current#
func (s *Shrinker) Current() []byteCurrent returns the best failing example found so far.
func (*Shrinker) Shrink#
func (s *Shrinker) Shrink() []byteShrink runs all shrinking passes and returns the minimized failing example. This is the main entry point for shrinking.
It orchestrates multiple passes, running them in rounds until a fixed point is reached (no more shrinking possible) or the call budget is exhausted.
type SliceGenerator#
SliceGenerator provides fluent API for slice generation
type SliceGenerator[T any] struct {
// contains filtered or unexported fields
}func Slice#
func Slice[T any](elem Gen[T]) *SliceGenerator[T]Slice creates a slice generator
func (*SliceGenerator[T]) Draw#
func (g *SliceGenerator[T]) Draw(d conjecture.DataSource) ([]T, error)Draw implements Gen[[]T]
func (*SliceGenerator[T]) Filter#
func (g *SliceGenerator[T]) Filter(pred func([]T) bool) Gen[[]T]Filter returns a generator that only produces slices satisfying the predicate
func (*SliceGenerator[T]) Len#
func (g *SliceGenerator[T]) Len(n int) *SliceGenerator[T]Len sets exact slice length
func (*SliceGenerator[T]) MaxLen#
func (g *SliceGenerator[T]) MaxLen(n int) *SliceGenerator[T]MaxLen sets maximum slice length
func (*SliceGenerator[T]) MinLen#
func (g *SliceGenerator[T]) MinLen(n int) *SliceGenerator[T]MinLen sets minimum slice length
func (*SliceGenerator[T]) NonEmpty#
func (g *SliceGenerator[T]) NonEmpty() *SliceGenerator[T]NonEmpty ensures slice has at least one element
func (*SliceGenerator[T]) String#
func (g *SliceGenerator[T]) String() stringString implements Gen[[]T]
type Source#
Source provides data for generators. It has two modes:
- Deterministic (Gen): counter-based, produces friendly values like “user_1”
- Random (randomSource): PRNG-based, explores full type space for property testing
type Source interface {
// DrawBits generates n random bits as a uint64.
DrawBits(n int) uint64
// WriteLog appends a message to the log if logging is enabled.
WriteLog(msg string)
// IsDeterministic returns true if this source generates predictable,
// friendly values (like Gen). Returns false for random property testing.
IsDeterministic() bool
// StartInterval marks the beginning of a labeled interval in the byte stream.
// Generators should call this at the start of Draw() to enable structure-aware shrinking.
StartInterval(label string)
// EndInterval marks the end of the current interval.
// Generators should call this at the end of Draw().
EndInterval()
}func AsSource#
func AsSource(d conjecture.DataSource) SourceAsSource converts a DataSource to a Source (exported version for generated code).
type SpecFactory#
SpecFactory builds values from specs.
type SpecFactory[T any, S any] struct {
S Source
NewSpec func() S
Build BuildWithSpec[T, S]
}func NewSpecFactory#
func NewSpecFactory[T any, S any](s Source, newSpec func() S, build BuildWithSpec[T, S]) *SpecFactory[T, S]func (*SpecFactory[T, S]) Make#
func (f *SpecFactory[T, S]) Make(opts ...Opt[S]) Tfunc (*SpecFactory[T, S]) Many#
func (f *SpecFactory[T, S]) Many(n int, opts ...Opt[S]) []Ttype StringGenerator#
StringGenerator provides a fluent API for building string generators
type StringGenerator struct {
// contains filtered or unexported fields
}func String#
func String() *StringGeneratorString creates a string generator
func (*StringGenerator) ASCII#
func (g *StringGenerator) ASCII() *StringGeneratorASCII generates only ASCII characters
func (*StringGenerator) Alpha#
func (g *StringGenerator) Alpha() *StringGeneratorAlpha generates only alphabetic characters
func (*StringGenerator) AlphaNum#
func (g *StringGenerator) AlphaNum() *StringGeneratorAlphaNum generates only alphanumeric characters
func (*StringGenerator) Draw#
func (g *StringGenerator) Draw(d conjecture.DataSource) (string, error)Draw implements Gen[string]
func (*StringGenerator) ExampleHint#
func (g *StringGenerator) ExampleHint(hint string) *StringGeneratorExampleHint sets a hint for deterministic generation. When using PrimitivesGen (factory mode), generates strings like “id_1”, “id_2” instead of “str_1”, “str_2”. Has no effect in property testing mode (ConjectureData).
func (*StringGenerator) Filter#
func (g *StringGenerator) Filter(pred func(string) bool) Gen[string]Filter returns a generator that only produces strings satisfying the predicate
func (*StringGenerator) Len#
func (g *StringGenerator) Len(n int) *StringGeneratorLen sets exact length
func (*StringGenerator) MaxLen#
func (g *StringGenerator) MaxLen(n int) *StringGeneratorMaxLen sets the maximum length
func (*StringGenerator) MinLen#
func (g *StringGenerator) MinLen(n int) *StringGeneratorMinLen sets the minimum length
func (*StringGenerator) NonEmpty#
func (g *StringGenerator) NonEmpty() *StringGeneratorNonEmpty ensures string is not empty
func (*StringGenerator) Prefix#
func (g *StringGenerator) Prefix(p string) *StringGeneratorPrefix adds a prefix to generated strings
func (*StringGenerator) Printable#
func (g *StringGenerator) Printable() *StringGeneratorPrintable generates only printable ASCII
func (*StringGenerator) String#
func (g *StringGenerator) String() stringString implements Gen[string]
func (*StringGenerator) Suffix#
func (g *StringGenerator) Suffix(s string) *StringGeneratorSuffix adds a suffix to generated strings
type T#
T is a testing helper for property-based tests. It implements the TestingT interface and can be used with AssertThat and other matchers. Unlike testing.T, calling Fatalf does not immediately terminate the test process, but instead panics with a sentinel value to stop the current property iteration.
type T struct {
Data *conjecture.ConjectureData // ConjectureData for drawing values
Source Source // Deprecated: kept for backward compatibility, will panic if used
// contains filtered or unexported fields
}func (*T) Assume#
func (t *T) Assume(condition bool)Assume skips the current property test iteration if the condition is false. This is useful for filtering generated values that don’t meet preconditions. Property will track how many tests were skipped and warn if the skip rate is high.
Example:
Property(t, func(t *T) {
n := Int().Range(1, 100).Draw(t, "n")
t.Assume(isPrime(n)) // Skip if not prime
// Test with prime numbers only
})func (*T) Errorf#
func (t *T) Errorf(format string, args ...any)Errorf records an error but allows the property test to continue. Multiple assertions can be checked before the property fails.
func (*T) Fatalf#
func (t *T) Fatalf(format string, args ...any)Fatalf records an error and immediately stops this property test iteration.
func (*T) Helper#
func (t *T) Helper()Helper marks the calling function as a test helper. This is a no-op for property testing but satisfies the TestingT interface.
func (*T) Logf#
func (t *T) Logf(format string, args ...any)Logf logs a message. During normal test execution, logs are discarded to avoid spam from multiple iterations. During the final replay of a failing test, logs are forwarded directly to testing.T.Logf with correct line attribution using the Helper() mechanism.
type TestingT#
TestingT is the minimal interface required by AssertThat and RequireThat. Both *testing.T and *testing.B satisfy this interface.
type TestingT interface {
Helper()
Errorf(format string, args ...interface{})
Fatalf(format string, args ...interface{})
Logf(format string, args ...interface{})
}Generated by gomarkdoc