gopter: github.com/leanovate/gopter Index | Examples | Files | Directories

package gopter

import "github.com/leanovate/gopter"

Package gopter contain the main interfaces of the GOlang Property TestER.

A simple property test might look like this:

func TestSqrt(t *testing.T) {
	properties := gopter.NewProperties(nil)

	properties.Property("greater one of all greater one", prop.ForAll(
		func(v float64) bool {
			return math.Sqrt(v) >= 1
		},
		gen.Float64Range(1, math.MaxFloat64),
	))

	properties.Property("squared is equal to value", prop.ForAll(
		func(v float64) bool {
			r := math.Sqrt(v)
			return math.Abs(r*r-v) < 1e-10*v
		},
		gen.Float64Range(0, math.MaxFloat64),
	))

	properties.TestingRun(t)
}

Generally a property is just a function that takes GenParameters and produces a PropResult:

type Prop func(*GenParameters) *PropResult

but usually you will use prop.ForAll, prop.ForAllNoShrink or arbitrary.ForAll. There is also the commands package, which can be helpful for stateful testing.

Code:

package main

import (
    "errors"
    "math"
    "strconv"
    "strings"

    "github.com/leanovate/gopter"
    "github.com/leanovate/gopter/gen"
    "github.com/leanovate/gopter/prop"
)

// Fizzbuzz: See https://wikipedia.org/wiki/Fizz_buzz
func fizzbuzz(number int) (string, error) {
    if number <= 0 {
        return "", errors.New("Undefined")
    }
    switch {
    case number%15 == 0:
        return "FizzBuzz", nil
    case number%3 == 0:
        return "Fizz", nil
    case number%5 == 0:
        return "Buzz", nil
    }
    return strconv.Itoa(number), nil
}

func main() {
    properties := gopter.NewProperties(nil)

    properties.Property("Undefined for all <= 0", prop.ForAll(
        func(number int) bool {
            result, err := fizzbuzz(number)
            return err != nil && result == ""
        },
        gen.IntRange(math.MinInt32, 0),
    ))

    properties.Property("Start with Fizz for all multiples of 3", prop.ForAll(
        func(i int) bool {
            result, err := fizzbuzz(i * 3)
            return err == nil && strings.HasPrefix(result, "Fizz")
        },
        gen.IntRange(1, math.MaxInt32/3),
    ))

    properties.Property("End with Buzz for all multiples of 5", prop.ForAll(
        func(i int) bool {
            result, err := fizzbuzz(i * 5)
            return err == nil && strings.HasSuffix(result, "Buzz")
        },
        gen.IntRange(1, math.MaxInt32/5),
    ))

    properties.Property("Int as string for all non-divisible by 3 or 5", prop.ForAll(
        func(number int) bool {
            result, err := fizzbuzz(number)
            if err != nil {
                return false
            }
            parsed, err := strconv.ParseInt(result, 10, 64)
            return err == nil && parsed == int64(number)
        },
        gen.IntRange(1, math.MaxInt32).SuchThat(func(v interface{}) bool {
            return v.(int)%3 != 0 && v.(int)%5 != 0
        }),
    ))

    // When using testing.T you might just use: properties.TestingRun(t)
    properties.Run(gopter.ConsoleReporter(false))
}

Example_labels demonstrates how labels may help, in case of more complex conditions. The output will be:

! Check spooky: Falsified after 0 passed tests.
> Labels of failing property: even result
a: 3
a_ORIGINAL (44 shrinks): 861384713
b: 0
b_ORIGINAL (1 shrinks): -642623569

Code:

package main

import (
    "github.com/leanovate/gopter"
    "github.com/leanovate/gopter/gen"
    "github.com/leanovate/gopter/prop"
)

func spookyCalculation(a, b int) int {
    if a < 0 {
        a = -a
    }
    if b < 0 {
        b = -b
    }
    return 2*b + 3*(2+(a+1)+b*(b+1))
}

// Example_labels demonstrates how labels may help, in case of more complex
// conditions.
// The output will be:
//  ! Check spooky: Falsified after 0 passed tests.
//  > Labels of failing property: even result
//  a: 3
//  a_ORIGINAL (44 shrinks): 861384713
//  b: 0
//  b_ORIGINAL (1 shrinks): -642623569
func main() {
    parameters := gopter.DefaultTestParameters()
    parameters.Rng.Seed(1234) // Just for this example to generate reproducable results
    parameters.MinSuccessfulTests = 10000

    properties := gopter.NewProperties(parameters)

    properties.Property("Check spooky", prop.ForAll(
        func(a, b int) string {
            result := spookyCalculation(a, b)
            if result < 0 {
                return "negative result"
            }
            if result%2 == 0 {
                return "even result"
            }
            return ""
        },
        gen.Int().WithLabel("a"),
        gen.Int().WithLabel("b"),
    ))

    // When using testing.T you might just use: properties.TestingRun(t)
    properties.Run(gopter.ConsoleReporter(false))
}

Code:

parameters := gopter.DefaultTestParameters()
parameters.Rng.Seed(1234) // Just for this example to generate reproducable results

properties := gopter.NewProperties(parameters)

properties.Property("greater one of all greater one", prop.ForAll(
    func(v float64) bool {
        return math.Sqrt(v) >= 1
    },
    gen.Float64().SuchThat(func(x float64) bool { return x >= 1.0 }),
))

properties.Property("squared is equal to value", prop.ForAll(
    func(v float64) bool {
        r := math.Sqrt(v)
        return math.Abs(r*r-v) < 1e-10*v
    },
    gen.Float64().SuchThat(func(x float64) bool { return x >= 0.0 }),
))

// When using testing.T you might just use: properties.TestingRun(t)
properties.Run(gopter.ConsoleReporter(false))

Output:

+ greater one of all greater one: OK, passed 100 tests.
+ squared is equal to value: OK, passed 100 tests.

Index

Examples

Package Files

bi_mapper.go derived_gen.go doc.go flag.go formated_reporter.go gen.go gen_parameters.go gen_result.go locked_source.go prop.go prop_arg.go prop_result.go properties.go reporter.go runner.go shrink.go test_parameters.go test_result.go

Constants

const (
    // PropProof THe property was proved (i.e. it is known to be correct and will be always true)
    PropProof propStatus = iota
    // PropTrue The property was true this time
    PropTrue
    // PropFalse The property was false this time
    PropFalse
    // PropUndecided The property has no clear outcome this time
    PropUndecided
    // PropError The property has generated an error
    PropError
)
const (
    // TestPassed indicates that the property check has passed.
    TestPassed testStatus = iota
    // TestProved indicates that the property has been proved.
    TestProved
    // TestFailed indicates that the property check has failed.
    TestFailed
    // TestExhausted indicates that the property check has exhausted, i.e. the generators have
    // generated too many empty results.
    TestExhausted
    // TestError indicates that the property check has finished with an error.
    TestError
)

Variables

var (
    // DefaultGenParams can be used as default für *GenParameters
    DefaultGenParams = DefaultGenParameters()
)
var NoShrink = Shrink(func() (interface{}, bool) {
    return nil, false
})

NoShrink is an empty shrink.

var NoShrinker = Shrinker(func(value interface{}) Shrink {
    return NoShrink
})

NoShrinker is a shrinker for NoShrink, i.e. a Shrinker that will not shrink any values. This is the default Shrinker if none is provided.

func NewLockedSource Uses

func NewLockedSource(seed int64) *lockedSource

NewLockedSource takes a seed and returns a new lockedSource for use with rand.New

type BiMapper Uses

type BiMapper struct {
    UpTypes    []reflect.Type
    DownTypes  []reflect.Type
    Downstream reflect.Value
    Upstream   reflect.Value
}

BiMapper is a bi-directional (or bijective) mapper of a tuple of values (up) to another tuple of values (down).

func NewBiMapper Uses

func NewBiMapper(downstream interface{}, upstream interface{}) *BiMapper

NewBiMapper creates a BiMapper of two functions `downstream` and its inverse `upstream`. That is: The return values of `downstream` must match the parameters of `upstream` and vice versa.

func (*BiMapper) ConvertDown Uses

func (b *BiMapper) ConvertDown(up []interface{}) []interface{}

ConvertDown calls the Downstream function on the elements of the up array and returns the results.

func (*BiMapper) ConvertUp Uses

func (b *BiMapper) ConvertUp(down []interface{}) []interface{}

ConvertUp calls the Upstream function on the arguments in the down array and returns the results.

type Flag Uses

type Flag struct {
    // contains filtered or unexported fields
}

Flag is a convenient helper for an atomic boolean

func (*Flag) Get Uses

func (f *Flag) Get() bool

Get the value of the flag

func (*Flag) Set Uses

func (f *Flag) Set()

Set the the flag

func (*Flag) Unset Uses

func (f *Flag) Unset()

Unset the flag

type FormatedReporter Uses

type FormatedReporter struct {
    // contains filtered or unexported fields
}

FormatedReporter reports test results in a human readable manager.

func (*FormatedReporter) ReportTestResult Uses

func (r *FormatedReporter) ReportTestResult(propName string, result *TestResult)

ReportTestResult reports a single property result

type Gen Uses

type Gen func(*GenParameters) *GenResult

Gen generator of arbitrary values. Usually properties are checked by verifing a condition holds true for arbitrary input parameters generated by a Gen.

IMPORTANT: Even though a generator is supposed to generate random values, it should do this in a reproducable way. Therefore a generator has to create the same result for the same GenParameters, i.e. ensure that you just use the RNG provided by GenParameters and no external one. If you just plug generators together you do not have to worry about this.

func CombineGens Uses

func CombineGens(gens ...Gen) Gen

CombineGens creates a generators from a list of generators. The result type will be a []interface{} containing the generated values of each generators in the list. Note: The combined generator will not have a sieve or shrinker.

func DeriveGen Uses

func DeriveGen(downstream interface{}, upstream interface{}, gens ...Gen) Gen

DeriveGen derives a generator with shrinkers from a sequence of other generators mapped by a bijective function (BiMapper)

func (Gen) FlatMap Uses

func (g Gen) FlatMap(f func(interface{}) Gen, resultType reflect.Type) Gen

FlatMap creates a derived generator by passing a generated value to a function which itself creates a generator.

func (Gen) Map Uses

func (g Gen) Map(f interface{}) Gen

Map creates a derived generators by mapping all generatored values with a given function. f: has to be a function with one parameter (matching the generated value) and a single return. Note: The derived generator will not have a sieve or shrinker. Note: The mapping function may have a second parameter "*GenParameters" Note: The first parameter of the mapping function and its return may be a *GenResult (this makes MapResult obsolete)

func (Gen) MapResult Uses

func (g Gen) MapResult(f func(*GenResult) *GenResult) Gen

MapResult creates a derived generator by mapping the GenResult directly. Contrary to `Map` and `FlatMap` this also allow the conversion of shrinkers and sieves, but implementation is more cumbersome. Deprecation note: Map now has the same functionality

func (Gen) Sample Uses

func (g Gen) Sample() (interface{}, bool)

Sample generate a sample value. Depending on the state of the RNG the generate might fail to provide a sample

func (Gen) SuchThat Uses

func (g Gen) SuchThat(f interface{}) Gen

SuchThat creates a derived generator by adding a sieve. f: has to be a function with one parameter (matching the generated value) returning a bool. All generated values are expected to satisfy

f(value) == true.

Use this care, if the sieve to to fine the generator will have many misses which results in an undecided property.

func (Gen) WithLabel Uses

func (g Gen) WithLabel(label string) Gen

WithLabel adds a label to a generated value. Labels are usually used for reporting for the arguments of a property check.

func (Gen) WithShrinker Uses

func (g Gen) WithShrinker(shrinker Shrinker) Gen

WithShrinker creates a derived generator with a specific shrinker

type GenParameters Uses

type GenParameters struct {
    MinSize        int
    MaxSize        int
    MaxShrinkCount int
    Rng            *rand.Rand
}

GenParameters encapsulates the parameters for all generators.

func DefaultGenParameters Uses

func DefaultGenParameters() *GenParameters

DefaultGenParameters creates default GenParameters.

func (*GenParameters) CloneWithSeed Uses

func (p *GenParameters) CloneWithSeed(seed int64) *GenParameters

CloneWithSeed clone the current parameters with a new seed. This is useful to create subsections that can rerun (provided you keep the seed)

func (*GenParameters) NextBool Uses

func (p *GenParameters) NextBool() bool

NextBool create a random boolean using the underlying Rng.

func (*GenParameters) NextInt64 Uses

func (p *GenParameters) NextInt64() int64

NextInt64 create a random int64 using the underlying Rng.

func (*GenParameters) NextUint64 Uses

func (p *GenParameters) NextUint64() uint64

NextUint64 create a random uint64 using the underlying Rng.

func (*GenParameters) WithSize Uses

func (p *GenParameters) WithSize(size int) *GenParameters

WithSize modifies the size parameter. The size parameter defines an upper bound for the size of generated slices or strings.

type GenResult Uses

type GenResult struct {
    Labels     []string
    Shrinker   Shrinker
    ResultType reflect.Type
    Result     interface{}
    Sieve      func(interface{}) bool
}

GenResult contains the result of a generator.

func NewEmptyResult Uses

func NewEmptyResult(resultType reflect.Type) *GenResult

NewEmptyResult creates an empty generator result. Unless the sieve does not explicitly allow it, empty (i.e. nil-valued) results are considered invalid.

func NewGenResult Uses

func NewGenResult(result interface{}, shrinker Shrinker) *GenResult

NewGenResult creates a new generator result from for a concrete value and shrinker. Note: The concrete value "result" not be nil

func (*GenResult) Retrieve Uses

func (r *GenResult) Retrieve() (interface{}, bool)

Retrieve gets the concrete generator result. If the result is invalid or does not pass the sieve there is no concrete value and the property using the generator should be undecided.

func (*GenResult) RetrieveAsValue Uses

func (r *GenResult) RetrieveAsValue() (reflect.Value, bool)

RetrieveAsValue get the concrete generator result as reflect value. If the result is invalid or does not pass the sieve there is no concrete value and the property using the generator should be undecided.

type Prop Uses

type Prop func(*GenParameters) *PropResult

Prop represent some kind of property that (drums please) can and should be checked

func SaveProp Uses

func SaveProp(prop Prop) Prop

SaveProp creates s save property by handling all panics from an inner property

func (Prop) Check Uses

func (prop Prop) Check(parameters *TestParameters) *TestResult

Check the property using specific parameters

type PropArg Uses

type PropArg struct {
    Arg     interface{}
    OrigArg interface{}
    Label   string
    Shrinks int
}

PropArg contains information about the specific values for a certain property check. This is mostly used for reporting when a property has falsified.

func NewPropArg Uses

func NewPropArg(genResult *GenResult, shrinks int, value, origValue interface{}) *PropArg

NewPropArg creates a new PropArg.

func (*PropArg) String Uses

func (p *PropArg) String() string

type PropArgs Uses

type PropArgs []*PropArg

PropArgs is a list of PropArg.

type PropResult Uses

type PropResult struct {
    Status propStatus
    Error  error
    Args   []*PropArg
    Labels []string
}

PropResult contains the result of a property

func NewPropResult Uses

func NewPropResult(success bool, label string) *PropResult

NewPropResult create a PropResult with label

func (*PropResult) AddArgs Uses

func (r *PropResult) AddArgs(args ...*PropArg) *PropResult

AddArgs add argument descriptors to the PropResult for reporting

func (*PropResult) And Uses

func (r *PropResult) And(other *PropResult) *PropResult

And combines two PropResult by an and operation. The resulting PropResult will be only true if both PropResults are true.

func (*PropResult) Success Uses

func (r *PropResult) Success() bool

Success checks if the result was successful

func (*PropResult) WithArgs Uses

func (r *PropResult) WithArgs(args []*PropArg) *PropResult

WithArgs sets argument descriptors to the PropResult for reporting

type Properties Uses

type Properties struct {
    // contains filtered or unexported fields
}

Properties is a collection of properties that should be checked in a test

func NewProperties Uses

func NewProperties(parameters *TestParameters) *Properties

NewProperties create new Properties with given test parameters. If parameters is nil default test parameters will be used

func (*Properties) Property Uses

func (p *Properties) Property(name string, prop Prop)

Property add/defines a property in a test.

func (*Properties) Run Uses

func (p *Properties) Run(reporter Reporter) bool

Run checks all definied propertiesand reports the result

func (*Properties) TestingRun Uses

func (p *Properties) TestingRun(t *testing.T, opts ...interface{})

TestingRun checks all definied properties with a testing.T context. This the preferred wait to run property tests as part of a go unit test.

type Reporter Uses

type Reporter interface {
    // ReportTestResult reports a single property result
    ReportTestResult(propName string, result *TestResult)
}

Reporter is a simple interface to report/format the results of a property check.

func ConsoleReporter Uses

func ConsoleReporter(verbose bool) Reporter

ConsoleReporter creates a FormatedReporter writing to the console (i.e. stdout)

func NewFormatedReporter Uses

func NewFormatedReporter(verbose bool, width int, output io.Writer) Reporter

NewFormatedReporter create a new formated reporter verbose toggles verbose output of the property results width is the maximal width per line output is the writer were the report will be written to

type Shrink Uses

type Shrink func() (interface{}, bool)

Shrink is a stream of shrinked down values. Once the result of a shrink is false, it is considered to be exhausted. Important notes for implementors:

* Ensure that the returned stream is finite, even though shrinking will
  eventually be aborted, infinite streams may result in very slow running
  test.
* Ensure that modifications to the returned value will not affect the
  internal state of your Shrink. If in doubt return by value not by reference

func ConcatShrinks Uses

func ConcatShrinks(shrinks ...Shrink) Shrink

ConcatShrinks concats an array of shrinks to a single shrinks

func (Shrink) All Uses

func (s Shrink) All() []interface{}

All collects all shrinks as a slice. Use with care as this might create large results depending on the complexity of the shrink

func (Shrink) Filter Uses

func (s Shrink) Filter(condition func(interface{}) bool) Shrink

Filter creates a shrink filtered by a condition

func (Shrink) Interleave Uses

func (s Shrink) Interleave(other Shrink) Shrink

Interleave this shrink with another Both shrinks are expected to produce the same result

func (Shrink) Map Uses

func (s Shrink) Map(f interface{}) Shrink

Map creates a shrink by applying a converter to each element of a shrink. f: has to be a function with one parameter (matching the generated value) and a single return.

type Shrinker Uses

type Shrinker func(value interface{}) Shrink

Shrinker creates a shrink for a given value

func CombineShrinker Uses

func CombineShrinker(shrinkers ...Shrinker) Shrinker

CombineShrinker create a shrinker by combining a list of shrinkers. The resulting shrinker will shrink an []interface{} where each element will be shrinked by the corresonding shrinker in 'shrinkers'. This method is implicitly used by CombineGens.

type TestParameters Uses

type TestParameters struct {
    MinSuccessfulTests int
    // MinSize is an (inclusive) lower limit on the size of the parameters
    MinSize int
    // MaxSize is an (exclusive) upper limit on the size of the parameters
    MaxSize         int
    MaxShrinkCount  int
    Seed            int64
    Rng             *rand.Rand
    Workers         int
    MaxDiscardRatio float64
}

TestParameters to run property tests

func DefaultTestParameters Uses

func DefaultTestParameters() *TestParameters

DefaultTestParameterWithSeeds creates reasonable default Parameters for most cases with an undefined RNG-seed

func DefaultTestParametersWithSeed Uses

func DefaultTestParametersWithSeed(seed int64) *TestParameters

DefaultTestParameterWithSeeds creates reasonable default Parameters for most cases based on a fixed RNG-seed

type TestResult Uses

type TestResult struct {
    Status    testStatus
    Succeeded int
    Discarded int
    Labels    []string
    Error     error
    Args      PropArgs
    Time      time.Duration
}

TestResult contains the result of a property property check.

func (*TestResult) Passed Uses

func (r *TestResult) Passed() bool

Passed checks if the check has passed

Directories

PathSynopsis
arbitraryPackage arbitrary contains helpers to create contexts of arbitrary values, i.e.
commandsPackage commands contains helpers to create stateful tests based on commands.
conveyPackage convey contains special assertion that come handy when using groper properties with goconvey.
genPackage gen contains all commonly used generators and shrinkers.
propPackage prop contains the most common implementations of a gopter.Prop.

Package gopter imports 13 packages (graph) and is imported by 21 packages. Updated 2018-11-19. Refresh now. Tools for package owners.