Documentation
¶
Overview ¶
Package arbitrary contains helpers to create contexts of arbitrary values, i.e. automatically combine generators as needed using reflection.
A simple example might look like this:
func TestIntParse(t *testing.T) { properties := gopter.NewProperties(nil) arbitraries := arbitrary.DefaultArbitraries() properties.Property("printed integers can be parsed", arbitraries.ForAll( func(a int64) bool { str := fmt.Sprintf("%d", a) parsed, err := strconv.ParseInt(str, 10, 64) return err == nil && parsed == a })) properties.TestingRun(t) }
Be aware that by default always the most generic generators are used. I.e. in the example above the gen.Int64 generator will be used and the condition will be tested for the full range of int64 numbers.
To adapt this one might register a generator for a specific type in an arbitraries context. I.e. by adding
arbitraries.RegisterGen(gen.Int64Range(-1000, 1000))
any generated int64 number will be between -1000 and 1000.
Example (Arbitrary_structs) ¶
package main import ( "fmt" "time" "github.com/leanovate/gopter" "github.com/leanovate/gopter/arbitrary" ) type MyStringType string type MyInt8Type int8 type MyInt16Type int16 type MyInt32Type int32 type MyInt64Type int64 type MyUInt8Type uint8 type MyUInt16Type uint16 type MyUInt32Type uint32 type MyUInt64Type uint64 type Foo struct { Name MyStringType Id1 MyInt8Type Id2 MyInt16Type Id3 MyInt32Type Id4 MyInt64Type Id5 MyUInt8Type Id6 MyUInt16Type Id7 MyUInt32Type Id8 MyUInt64Type ATime time.Time ATimePtr *time.Time } func (f Foo) ToString() string { return fmt.Sprintf("For(%s, %d, %d, %d, %d, %d, %d, %d, %d, %v, %v)", f.Name, f.Id1, f.Id2, f.Id3, f.Id4, f.Id5, f.Id6, f.Id7, f.Id8, f.ATime, f.ATimePtr) } func main() { time.Local = time.UTC parameters := gopter.DefaultTestParametersWithSeed(1234) // Example should generate reproducible results, otherwise DefaultTestParameters() will suffice arbitraries := arbitrary.DefaultArbitraries() properties := gopter.NewProperties(parameters) properties.Property("MyInt64", arbitraries.ForAll( func(id MyInt64Type) bool { return id > -1000 })) properties.Property("MyUInt32Type", arbitraries.ForAll( func(id MyUInt32Type) bool { return id < 2000 })) properties.Property("Foo", arbitraries.ForAll( func(foo *Foo) bool { return foo.ATime.After(time.Unix(0, 0)) })) properties.Property("Foo2", arbitraries.ForAll( func(foo Foo) bool { return foo.ATimePtr == nil || foo.ATimePtr.Before(time.Unix(20000, 0)) })) properties.Run(gopter.ConsoleReporter(false)) }
Output: ! MyInt64: Falsified after 6 passed tests. ARG_0: -1000 ARG_0_ORIGINAL (54 shrinks): -1601066829744837253 ! MyUInt32Type: Falsified after 0 passed tests. ARG_0: 2000 ARG_0_ORIGINAL (23 shrinks): 2161922319 + Foo: OK, passed 100 tests. ! Foo2: Falsified after 1 passed tests. ARG_0: {Name: Id1:0 Id2:0 Id3:0 Id4:0 Id5:0 Id6:0 Id7:0 Id8:0 ATime:1970-01-01 00:00:00 +0000 UTC ATimePtr:1970-01-01 05:33:20 +0000 UTC} ARG_0_ORIGINAL (40 shrinks): {Name: Id1:-67 Id2:27301 Id3:-1350752892 Id4:7128486677722156226 Id5:208 Id6:28663 Id7:4178604448 Id8:16360504079646654692 ATime:2239-08-20 23:46:28.063412239 +0000 UTC ATimePtr:5468-08-19 13:09:39.171622464 +0000 UTC}
Example (Parseint) ¶
package main import ( "fmt" "strconv" "github.com/leanovate/gopter" "github.com/leanovate/gopter/arbitrary" ) func main() { parameters := gopter.DefaultTestParametersWithSeed(1234) // Example should generate reproducible results, otherwise DefaultTestParameters() will suffice arbitraries := arbitrary.DefaultArbitraries() properties := gopter.NewProperties(parameters) properties.Property("printed integers can be parsed", arbitraries.ForAll( func(a int64) bool { str := fmt.Sprintf("%d", a) parsed, err := strconv.ParseInt(str, 10, 64) return err == nil && parsed == a })) // When using testing.T you might just use: properties.TestingRun(t) properties.Run(gopter.ConsoleReporter(false)) }
Output: + printed integers can be parsed: OK, passed 100 tests.
Example (Quadratic) ¶
package main import ( "errors" "math/cmplx" "github.com/leanovate/gopter" "github.com/leanovate/gopter/arbitrary" "github.com/leanovate/gopter/gen" ) type QudraticEquation struct { A, B, C complex128 } func (q *QudraticEquation) Eval(x complex128) complex128 { return q.A*x*x + q.B*x + q.C } func (q *QudraticEquation) Solve() (complex128, complex128, error) { if q.A == 0 { return 0, 0, errors.New("No solution") } v := q.B*q.B - 4*q.A*q.C v = cmplx.Sqrt(v) return (-q.B + v) / 2 / q.A, (-q.B - v) / 2 / q.A, nil } func main() { parameters := gopter.DefaultTestParametersWithSeed(1234) // Example should generate reproducible results, otherwise DefaultTestParameters() will suffice arbitraries := arbitrary.DefaultArbitraries() arbitraries.RegisterGen(gen.Complex128Box(-1e8-1e8i, 1e8+1e8i)) // Only use complex values within a range properties := gopter.NewProperties(parameters) properties.Property("Quadratic equations can be solved (as pointer)", arbitraries.ForAll( func(quadratic *QudraticEquation) bool { x1, x2, err := quadratic.Solve() if err != nil { return true } return cmplx.Abs(quadratic.Eval(x1)) < 1e-5 && cmplx.Abs(quadratic.Eval(x2)) < 1e-5 })) properties.Property("Quadratic equations can be solved (as struct)", arbitraries.ForAll( func(quadratic QudraticEquation) bool { x1, x2, err := quadratic.Solve() if err != nil { return true } return cmplx.Abs(quadratic.Eval(x1)) < 1e-5 && cmplx.Abs(quadratic.Eval(x2)) < 1e-5 })) properties.Property("Quadratic equations can be solved alternative", arbitraries.ForAll( func(a, b, c complex128) bool { quadratic := &QudraticEquation{ A: a, B: b, C: c, } x1, x2, err := quadratic.Solve() if err != nil { return true } return cmplx.Abs(quadratic.Eval(x1)) < 1e-5 && cmplx.Abs(quadratic.Eval(x2)) < 1e-5 })) // When using testing.T you might just use: properties.TestingRun(t) properties.Run(gopter.ConsoleReporter(false)) }
Output: + Quadratic equations can be solved (as pointer): OK, passed 100 tests. + Quadratic equations can be solved (as struct): OK, passed 100 tests. + Quadratic equations can be solved alternative: OK, passed 100 tests.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Arbitraries ¶
type Arbitraries struct {
// contains filtered or unexported fields
}
Arbitraries defines a context to generate arbitrary values of any kind. Values are generated by either providing a generator for a specific type or by creating a generator on the fly using golang reflection.
func DefaultArbitraries ¶
func DefaultArbitraries() *Arbitraries
DefaultArbitraries creates a default arbitrary context with the widest possible ranges for all types.
func (*Arbitraries) ForAll ¶
func (a *Arbitraries) ForAll(condition interface{}) gopter.Prop
ForAll creates a property that requires the check condition to be true for all values, if the condition falsiies the generated values will be shrunk.
"condition" has to be a function with the any number of parameters that can generated in context of the Arbitraries. The function may return a simple bool, a *PropResult, a boolean with error or a *PropResult with error.
func (*Arbitraries) GenForType ¶
func (a *Arbitraries) GenForType(rt reflect.Type) gopter.Gen
GenForType gets a generator for a generator for a type
func (*Arbitraries) RegisterGen ¶
func (a *Arbitraries) RegisterGen(gen gopter.Gen)
RegisterGen registers a generator