check: github.com/powerman/check Index | Files

package check

import "github.com/powerman/check"

Package check provide helpers to complement Go testing package.

Features

This package is like testify/assert on steroids. :)

- Compelling output from failed tests:
  - Very easy-to-read dumps for expected and actual values.
  - Same text diff you loved in testify/assert.
  - Also visual diff in GoConvey web UI, if you use it (recommended).
- Statistics with amount of passed/failed checks.
- Colored output in terminal.
- 100% compatible with testing package - check package just provide
  convenient wrappers for *testing.T methods and doesn't introduce
  new concepts like BDD, custom test suite or unusual execution flow.
- All checks you may ever need! :)
- Very easy to add your own check functions.
- Concise, handy and consistent API, without dot-import!

Quickstart

Just wrap each (including subtests) *testing.T using check.T() and write tests as usually with testing package. Call new methods provided by this package to have more clean/concise test code and cool dump/diff.

import "github.com/powerman/check"

func TestSomething(tt *testing.T) {
	t := check.T(tt)
	t.Equal(2, 2)
	t.Log("You can use new t just like usual *testing.T")
	t.Run("Subtests/Parallel example", func(tt *testing.T) {
		t := check.T(tt)
		t.Parallel()
		t.NotEqual(2, 3, "should not be 3!")
		obj, err := NewObj()
		if t.Nil(err) {
			t.Match(obj.field, `^\d+$`)
		}
	})
}

To get optional statistics about executed checkers add:

func TestMain(m *testing.M) { check.TestMain(m) }

When use goconvey tool, to get nice diff in web UI add:

import _ "github.com/smartystreets/goconvey/convey"

Hints

★ How to check for errors:

// If you just want nil:
t.Nil(err)
t.Err(err, nil)

// Check for (absence of) concrete (possibly wrapped) error:
t.Err(err, io.EOF)
t.NotErr(err, io.EOF) // nil is not io.EOF, so it's ok too

// When need to match by error's text:
t.Match(err, "file.*permission")

// Use Equal ONLY when checking for same instance:
t.Equal(io.EOF, io.EOF)                // this works
t.Equal(io.EOF, errors.New("EOF"))     // this doesn't work!
t.Err(io.EOF, errors.New("EOF"))       // this works
t.DeepEqual(io.EOF, errors.New("EOF")) // this works too

★ Each check returns bool, so you can easily skip problematic code:

if t.Nil(err) {
	t.Match(obj.field, `^\d+$`)
}

★ You can turn any check into assertion to stop test immediately:

t.Must(t.Nil(err))

★ You can provide extra description to each check:

t.Equal(got, want, "Just msg: will Print(), % isn't special")
t.Equal(got, want, "Msg with args: will Printf(): %v", extra)

★ There are short synonyms for checks implementing usual ==, !=, etc.:

t.EQ(got, want) // same as t.Equal
t.NE(got, want) // same as t.NotEqual
t.LT(got, want) // same as t.Less
t.LE(got, want) // same as t.LessOrEqual
t.GT(got, want) // same as t.Greater
t.GE(got, want) // same as t.GreaterOrEqual

★ If you need custom check, which isn't available out-of-box - see Should checker, it'll let you plug in your own checker with ease.

★ It will panic when called with arg of wrong type - because this means bug in your test.

★ If you don't see colors in `go test` output it may happens because of two reasons: either your $TERM doesn't contain substring "color" or you're running `go test path/to/your/package`. To force colored output in last case just set this environment variable:

export GO_TEST_COLOR=1

Contents

There are few special functions (assertion, custom checkers, etc.).

Must
Should
TODO

Everything else are just trivial (mostly) checkers which works in obvious way and accept values of any types which makes sense (and panics on everything else).

Nil             NotNil
Zero            NotZero
True            False

Equal           NotEqual           EQ  NE
DeepEqual       NotDeepEqual
Err             NotErr
BytesEqual      NotBytesEqual
JSONEqual

Greater         LessOrEqual        GT  LE
Less            GreaterOrEqual     LT  GE
Between         NotBetween
BetweenOrEqual  NotBetweenOrEqual
InDelta         NotInDelta
InSMAPE         NotInSMAPE

Len             NotLen
Match           NotMatch
HasPrefix       NotHasPrefix
HasSuffix       NotHasSuffix
HasKey          NotHasKey
Contains        NotContains

HasType         NotHasType
Implements      NotImplements

Panic           NotPanic
PanicMatch      PanicNotMatch

Index

Package Files

check.go color.go color_linux.go doc.go dump.go flags.go goconvey.go stats.go util.go

func Report Uses

func Report()

Report output statistics about passed/failed checks. It should be called from TestMain after m.Run(), for ex.:

func TestMain(m *testing.M) {
	code := m.Run()
	check.Report()
	os.Exit(code)
}

If this is all you need - just use TestMain instead.

func TestMain Uses

func TestMain(m *testing.M)

TestMain provides same default implementation as used by testing package with extra Report call to output statistics. Usage:

func TestMain(m *testing.M) { check.TestMain(m) }

type C Uses

type C struct {
    *testing.T
    // contains filtered or unexported fields
}

C wraps *testing.T to make it convenient to call checkers in test.

func T Uses

func T(tt *testing.T) *C

T create and return new *C, which wraps given tt and supposed to be used inplace of it, providing you with access to many useful helpers in addition to standard methods of *testing.T.

It's convenient to rename Test function's arg from t to something else, create wrapped variable with usual name t and use only t:

func TestSomething(tt *testing.T) {
	t := check.T(tt)
	// use only t in test and don't touch tt anymore
}

func (*C) Between Uses

func (t *C) Between(actual, min, max interface{}, msg ...interface{}) bool

Between checks for min < actual < max.

All three actual, min and max must be either:

- signed integers
- unsigned integers
- floats
- strings
- time.Time

func (*C) BetweenOrEqual Uses

func (t *C) BetweenOrEqual(actual, min, max interface{}, msg ...interface{}) bool

BetweenOrEqual checks for min <= actual <= max.

All three actual, min and max must be either:

- signed integers
- unsigned integers
- floats
- strings
- time.Time

func (*C) BytesEqual Uses

func (t *C) BytesEqual(actual, expected []byte, msg ...interface{}) bool

BytesEqual checks for bytes.Equal(actual, expected).

Hint: BytesEqual([]byte{}, []byte(nil)) is true (unlike DeepEqual).

func (*C) Contains Uses

func (t *C) Contains(actual, expected interface{}, msg ...interface{}) bool

Contains checks is actual contains substring/element expected.

Element of array/slice/map is checked using == expected.

Type of expected depends on type of actual:

- if actual is a string, then expected should be a string
- if actual is an array, then expected should have array's element type
- if actual is a slice,  then expected should have slice's element type
- if actual is a map,    then expected should have map's value type

Hint: In a map it looks for a value, if you need to look for a key - use HasKey instead.

func (*C) DeepEqual Uses

func (t *C) DeepEqual(actual, expected interface{}, msg ...interface{}) bool

DeepEqual checks for reflect.DeepEqual(actual, expected).

func (*C) EQ Uses

func (t *C) EQ(actual, expected interface{}, msg ...interface{}) bool

EQ is a synonym for Equal.

func (*C) Equal Uses

func (t *C) Equal(actual, expected interface{}, msg ...interface{}) bool

Equal checks for actual == expected.

Note: For time.Time it uses actual.Equal(expected) instead.

func (*C) Err Uses

func (t *C) Err(actual, expected error, msg ...interface{}) bool

Err checks is actual error is the same as expected error.

It tries to recursively unwrap actual before checking using errors.Unwrap() and github.com/pkg/errors.Cause().

They may be a different instances, but must have same type and value.

Checking for nil is okay, but using Nil(actual) instead is more clean.

func (*C) False Uses

func (t *C) False(cond bool, msg ...interface{}) bool

False checks for cond == false.

func (*C) GE Uses

func (t *C) GE(actual, expected interface{}, msg ...interface{}) bool

GE is a synonym for GreaterOrEqual.

func (*C) GT Uses

func (t *C) GT(actual, expected interface{}, msg ...interface{}) bool

GT is a synonym for Greater.

func (*C) Greater Uses

func (t *C) Greater(actual, expected interface{}, msg ...interface{}) bool

Greater checks for actual > expected.

Both actual and expected must be either:

- signed integers
- unsigned integers
- floats
- strings
- time.Time

func (*C) GreaterOrEqual Uses

func (t *C) GreaterOrEqual(actual, expected interface{}, msg ...interface{}) bool

GreaterOrEqual checks for actual >= expected.

Both actual and expected must be either:

- signed integers
- unsigned integers
- floats
- strings
- time.Time

func (*C) HasKey Uses

func (t *C) HasKey(actual, expected interface{}, msg ...interface{}) bool

HasKey checks is actual has key expected.

func (*C) HasPrefix Uses

func (t *C) HasPrefix(actual, expected interface{}, msg ...interface{}) bool

HasPrefix checks for strings.HasPrefix(actual, expected).

Both actual and expected may have any of these types:

- string       - will use as is
- []byte       - will convert with string()
- []rune       - will convert with string()
- fmt.Stringer - will convert with actual.String()
- error        - will convert with actual.Error()
- nil          - check will always fail

func (*C) HasSuffix Uses

func (t *C) HasSuffix(actual, expected interface{}, msg ...interface{}) bool

HasSuffix checks for strings.HasSuffix(actual, expected).

Both actual and expected may have any of these types:

- string       - will use as is
- []byte       - will convert with string()
- []rune       - will convert with string()
- fmt.Stringer - will convert with actual.String()
- error        - will convert with actual.Error()
- nil          - check will always fail

func (*C) HasType Uses

func (t *C) HasType(actual, expected interface{}, msg ...interface{}) bool

HasType checks is actual has same type as expected.

func (*C) Implements Uses

func (t *C) Implements(actual, expected interface{}, msg ...interface{}) bool

Implements checks is actual implements interface pointed by expected.

You must use pointer to interface type in expected:

t.Implements(os.Stdin, (*io.Reader)(nil))

func (*C) InDelta Uses

func (t *C) InDelta(actual, expected, delta interface{}, msg ...interface{}) bool

InDelta checks for expected-delta <= actual <= expected+delta.

All three actual, expected and delta must be either:

- signed integers
- unsigned integers
- floats
- time.Time (in this case delta must be time.Duration)

func (*C) InSMAPE Uses

func (t *C) InSMAPE(actual, expected interface{}, smape float64, msg ...interface{}) bool

InSMAPE checks that actual and expected have a symmetric mean absolute percentage error (SMAPE) is less than given smape.

Both actual and expected must be either:

- signed integers
- unsigned integers
- floats

Allowed smape values are: 0.0 < smape < 100.0.

Used formula returns SMAPE value between 0 and 100 (percents):

- 0.0   when actual == expected
- ~0.5  when they differs in ~1%
- ~5    when they differs in ~10%
- ~20   when they differs in 1.5 times
- ~33   when they differs in 2 times
- 50.0  when they differs in 3 times
- ~82   when they differs in 10 times
- 99.0+ when actual and expected differs in 200+ times
- 100.0 when only one of actual or expected is 0 or one of them is
        positive while another is negative

func (*C) JSONEqual Uses

func (t *C) JSONEqual(actual, expected interface{}, msg ...interface{}) bool

JSONEqual normalize formatting of actual and expected (if they're valid JSON) and then checks for bytes.Equal(actual, expected).

Both actual and expected may have any of these types:

- string
- []byte
- json.RawMessage
- *json.RawMessage
- nil

In case any of actual or expected is nil or empty or (for string or []byte) is invalid JSON - check will fail.

func (*C) LE Uses

func (t *C) LE(actual, expected interface{}, msg ...interface{}) bool

LE is a synonym for LessOrEqual.

func (*C) LT Uses

func (t *C) LT(actual, expected interface{}, msg ...interface{}) bool

LT is a synonym for Less.

func (*C) Len Uses

func (t *C) Len(actual interface{}, expected int, msg ...interface{}) bool

Len checks is len(actual) == expected.

func (*C) Less Uses

func (t *C) Less(actual, expected interface{}, msg ...interface{}) bool

Less checks for actual < expected.

Both actual and expected must be either:

- signed integers
- unsigned integers
- floats
- strings
- time.Time

func (*C) LessOrEqual Uses

func (t *C) LessOrEqual(actual, expected interface{}, msg ...interface{}) bool

LessOrEqual checks for actual <= expected.

Both actual and expected must be either:

- signed integers
- unsigned integers
- floats
- strings
- time.Time

func (*C) Match Uses

func (t *C) Match(actual, regex interface{}, msg ...interface{}) bool

Match checks for regex.MatchString(actual).

Regex type can be either *regexp.Regexp or string.

Actual type can be:

- string       - will match with actual
- []byte       - will match with string(actual)
- []rune       - will match with string(actual)
- fmt.Stringer - will match with actual.String()
- error        - will match with actual.Error()
- nil          - will not match (even with empty regex)

func (*C) Must Uses

func (t *C) Must(continueTest bool, msg ...interface{})

Must interrupt test using t.FailNow if called with false value.

This provides easy way to turn any check into assertion:

t.Must(t.Nil(err))

func (*C) NE Uses

func (t *C) NE(actual, expected interface{}, msg ...interface{}) bool

NE is a synonym for NotEqual.

func (*C) Nil Uses

func (t *C) Nil(actual interface{}, msg ...interface{}) bool

Nil checks for actual == nil.

There is one subtle difference between this check and Go `== nil` (if this surprises you then you should read https://golang.org/doc/faq#nil_error first):

var intPtr *int
var empty interface{}
var notEmpty interface{} = intPtr
t.True(intPtr == nil)   // TRUE
t.True(empty == nil)    // TRUE
t.True(notEmpty == nil) // FALSE

When you call this function your actual value will be stored in interface{} argument, and this makes any typed nil pointer value `!= nil` inside this function (just like in example above happens with notEmpty variable).

As it is very common case to check some typed pointer using Nil this check has to work around and detect nil even if usual `== nil` return false. But this has nasty side effect: if actual value already was of interface type and contains some typed nil pointer (which is usually bad thing and should be avoid) then Nil check will pass (which may be not what you want/expect):

t.Nil(nil)              // TRUE
t.Nil(intPtr)           // TRUE
t.Nil(empty)            // TRUE
t.Nil(notEmpty)         // WARNING: also TRUE!

Second subtle case is less usual: uintptr(0) is sorta nil, but not really, so Nil(uintptr(0)) will fail. Nil(unsafe.Pointer(nil)) will also fail, for the same reason. Please do not use this and consider this behaviour undefined, because it may change in the future.

func (*C) NotBetween Uses

func (t *C) NotBetween(actual, min, max interface{}, msg ...interface{}) bool

NotBetween checks for actual <= min or max <= actual.

All three actual, min and max must be either:

- signed integers
- unsigned integers
- floats
- strings
- time.Time

func (*C) NotBetweenOrEqual Uses

func (t *C) NotBetweenOrEqual(actual, min, max interface{}, msg ...interface{}) bool

NotBetweenOrEqual checks for actual < min or max < actual.

All three actual, min and max must be either:

- signed integers
- unsigned integers
- floats
- strings
- time.Time

func (*C) NotBytesEqual Uses

func (t *C) NotBytesEqual(actual, expected []byte, msg ...interface{}) bool

NotBytesEqual checks for !bytes.Equal(actual, expected).

Hint: NotBytesEqual([]byte{}, []byte(nil)) is false (unlike NotDeepEqual).

func (*C) NotContains Uses

func (t *C) NotContains(actual, expected interface{}, msg ...interface{}) bool

NotContains checks is actual not contains substring/element expected.

See Contains about supported actual/expected types and check logic.

func (*C) NotDeepEqual Uses

func (t *C) NotDeepEqual(actual, expected interface{}, msg ...interface{}) bool

NotDeepEqual checks for !reflect.DeepEqual(actual, expected).

func (*C) NotEqual Uses

func (t *C) NotEqual(actual, expected interface{}, msg ...interface{}) bool

NotEqual checks for actual != expected.

func (*C) NotErr Uses

func (t *C) NotErr(actual, expected error, msg ...interface{}) bool

NotErr checks is actual error is not the same as expected error.

It tries to recursively unwrap actual before checking using errors.Unwrap() and github.com/pkg/errors.Cause().

They must have either different types or values (or one should be nil). Different instances with same type and value will be considered the same error, and so is both nil.

func (*C) NotHasKey Uses

func (t *C) NotHasKey(actual, expected interface{}, msg ...interface{}) bool

NotHasKey checks is actual has no key expected.

func (*C) NotHasPrefix Uses

func (t *C) NotHasPrefix(actual, expected interface{}, msg ...interface{}) bool

NotHasPrefix checks for !strings.HasPrefix(actual, expected).

See HasPrefix about supported actual/expected types and check logic.

func (*C) NotHasSuffix Uses

func (t *C) NotHasSuffix(actual, expected interface{}, msg ...interface{}) bool

NotHasSuffix checks for !strings.HasSuffix(actual, expected).

See HasSuffix about supported actual/expected types and check logic.

func (*C) NotHasType Uses

func (t *C) NotHasType(actual, expected interface{}, msg ...interface{}) bool

NotHasType checks is actual has not same type as expected.

func (*C) NotImplements Uses

func (t *C) NotImplements(actual, expected interface{}, msg ...interface{}) bool

NotImplements checks is actual does not implements interface pointed by expected.

You must use pointer to interface type in expected:

t.NotImplements(os.Stdin, (*fmt.Stringer)(nil))

func (*C) NotInDelta Uses

func (t *C) NotInDelta(actual, expected, delta interface{}, msg ...interface{}) bool

NotInDelta checks for actual < expected-delta or expected+delta < actual.

All three actual, expected and delta must be either:

- signed integers
- unsigned integers
- floats
- time.Time (in this case delta must be time.Duration)

func (*C) NotInSMAPE Uses

func (t *C) NotInSMAPE(actual, expected interface{}, smape float64, msg ...interface{}) bool

NotInSMAPE checks that actual and expected have a symmetric mean absolute percentage error (SMAPE) is greater than or equal to given smape.

See InSMAPE about supported actual/expected types and check logic.

func (*C) NotLen Uses

func (t *C) NotLen(actual interface{}, expected int, msg ...interface{}) bool

NotLen checks is len(actual) != expected.

func (*C) NotMatch Uses

func (t *C) NotMatch(actual, regex interface{}, msg ...interface{}) bool

NotMatch checks for !regex.MatchString(actual).

See Match about supported actual/regex types and check logic.

func (*C) NotNil Uses

func (t *C) NotNil(actual interface{}, msg ...interface{}) bool

NotNil checks for actual != nil.

See Nil about subtle case in check logic.

func (*C) NotPanic Uses

func (t *C) NotPanic(actual func(), msg ...interface{}) bool

NotPanic checks is actual() don't panics.

It is able to detect panic(nil)… but you should try to avoid using this.

func (*C) NotZero Uses

func (t *C) NotZero(actual interface{}, msg ...interface{}) bool

NotZero checks is actual is not zero value of it's type.

func (*C) Panic Uses

func (t *C) Panic(actual func(), msg ...interface{}) bool

Panic checks is actual() panics.

It is able to detect panic(nil)… but you should try to avoid using this.

func (*C) PanicMatch Uses

func (t *C) PanicMatch(actual func(), regex interface{}, msg ...interface{}) bool

PanicMatch checks is actual() panics and panic text match regex.

Regex type can be either *regexp.Regexp or string.

In case of panic(nil) it will match like panic("<nil>").

func (*C) PanicNotMatch Uses

func (t *C) PanicNotMatch(actual func(), regex interface{}, msg ...interface{}) bool

PanicNotMatch checks is actual() panics and panic text not match regex.

Regex type can be either *regexp.Regexp or string.

In case of panic(nil) it will match like panic("<nil>").

func (*C) Parallel Uses

func (t *C) Parallel()

Parallel implements an internal workaround which have no visible effect, so you should just call t.Parallel() as you usually do - it will work as expected.

func (*C) Should Uses

func (t *C) Should(anyShouldFunc interface{}, args ...interface{}) bool

Should use user-provided check function to do actual check.

anyShouldFunc must have type ShouldFunc1 or ShouldFunc2. It should return true if check was successful. There is no need to call t.Error in anyShouldFunc - this will be done automatically when it returns.

args must contain at least 1 element for ShouldFunc1 and at least 2 elements for ShouldFunc2. Rest of elements will be processed as usual msg ...interface{} param.

Example:

func bePositive(_ *check.C, actual interface{}) bool {
	return actual.(int) > 0
}
func TestCustomCheck(tt *testing.T) {
	t := check.T(tt)
	t.Should(bePositive, 42, "custom check!!!")
}

func (*C) TODO Uses

func (t *C) TODO() *C

TODO create and return new *C, which have only one difference from original one: every passing check is now handled as failed and vice versa (this doesn't affect boolean value returned by check). You can continue using both old and new *C at same time.

Swapping passed/failed gives you ability to temporary mark some failed test as passed. For example, this may be useful to avoid broken builds in CI. This is often better than commenting, deleting or skipping broken test because it will continue to execute, and eventually when reason why it fails will be fixed this test will became failed again - notifying you the mark can and should be removed from this test now.

func TestSomething(tt *testing.T) {
	t := check.T(tt)
	// Normal tests.
	t.True(true)
	// If you need to mark just one/few broken tests:
	t.TODO().True(false)
	t.True(true)
	// If there are several broken tests mixed with working ones:
	todo := t.TODO()
	t.True(true)
	todo.True(false)
	t.True(true)
	if todo.True(false) {
		panic("never here")
	}
	// If all tests below this point are broken:
	t = t.TODO()
	t.True(false)
	...
}

func (*C) True Uses

func (t *C) True(cond bool, msg ...interface{}) bool

True checks for cond == true.

This can be useful to use your own custom checks, but this way you won't get nice dump/diff for actual/expected values. You'll still have statistics about passed/failed checks and it's shorter than usual:

if !cond {
	t.Errorf(msg...)
}

func (*C) Zero Uses

func (t *C) Zero(actual interface{}, msg ...interface{}) bool

Zero checks is actual is zero value of it's type.

type ShouldFunc1 Uses

type ShouldFunc1 func(t *C, actual interface{}) bool

ShouldFunc1 is like Nil or Zero.

type ShouldFunc2 Uses

type ShouldFunc2 func(t *C, actual, expected interface{}) bool

ShouldFunc2 is like Equal or Match.

Package check imports 23 packages (graph) and is imported by 1 packages. Updated 2019-11-07. Refresh now. Tools for package owners.