testy: github.com/xdg/testy Index | Files

package testy

import "github.com/xdg/testy"

Package testy is an extensible facade around Go's core testing library.

Go's core testing package doesn't let you refactor repetitive tests without reporting errors from the wrong place in the code. Testy implements a facade around the testing package and hijacks its logging features. This means:

* You can report test errors at any level up the call stack.

* You can label all errors in a scope to disambiguate repetitive tests.

The downside is an extra level of log message nesting (which your editor's quickfix window should ignore, anyway).

It gives a few convenient helper functions for common cases and makes it easy to implement your own.

The following example shows how to set up testy and use test helpers. In particular, note the use of 'defer' and a closure to schedule testy to output the log at the end of the function's execution.

package example

import (
	"github.com/xdg/testy"
	"testing"
)

func TestExample(t *testing.T) {
	is := testy.New(t)
	defer func() { t.Logf(is.Done()) }()

	is.True(1+1 == 3)
	is.False(2 == 2)

	is.Equal(1, 2)
	is.Equal(1.0, 1)
	is.Equal("foo\tbar", "foo\tbaz")
	is.Equal(true, false)

	is.Unequal(42, 42)

	is.NotNil(is)
}

Each error will be reported at the calling line. Calls to 'Equal' and 'Unequal' will return diagnostic details. Here is how some of the output would look in Vim's quickfix window:

...
_examples/example_test.go|15| Values were not equal:
|| 			   Got: 1 (int)
|| 			Wanted: 2 (int)
_examples/example_test.go|16| Values were not equal:
|| 			   Got: 1 (float64)
|| 			Wanted: 1 (int)
_examples/example_test.go|17| Values were not equal:
|| 			   Got: "foo\tbar"
|| 			Wanted: "foo\tbaz"
...

You can use the 'Uplevel' and 'Label' methods to return new facades, which you can use to implement custom helpers in various ways:

func TestExample(t *testing.T) {
	is := testy.New(t)
	defer func() { t.Logf(is.Done()) }()

	// Check for numbers equal to 3
	for i := 1; i <= 5; i++ {
		is.Label("Checking", i).True(i == 3) // Line 13
	}

	// Check for positive, even numbers
	for i := -1; i <= 2; i++ {
		checkEvenPositive(is, i)             // Line 18
	}
}

func checkEvenPositive(is *testy.T, n int) {
	// Report one level up with a custom label
	is = is.Uplevel(1).Label("Testing", n)

	if n < 1 {
		is.Error("Value was not positive")
	}
	if n%2 != 0 {
		is.Error("Value was not even")
	}
}

The example above would return errors to a quickfix window like this:

...
_examples/example_test.go|13| Checking 1: Expression was not true
_examples/example_test.go|13| Checking 2: Expression was not true
_examples/example_test.go|13| Checking 4: Expression was not true
_examples/example_test.go|13| Checking 5: Expression was not true
_examples/example_test.go|18| Testing -1: Value was not positive
_examples/example_test.go|18| Testing -1: Value was not even
_examples/example_test.go|18| Testing 0: Value was not positive
_examples/example_test.go|18| Testing 1: Value was not even
...

Index

Package Files

testy.go

type T Uses

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

T is a facade around the testing.T type passed to Test functions. It intercepts log messages to attribute them to the correct level of the call stack.

func New Uses

func New(t *testing.T) *T

New wraps a testy.T struct around a testing.T struct. The resulting struct can be used in the same way the testing.T struct would be, plus has additional methods specific to Testy. It calls NewCase with the calling function's name as the test case name.

func NewCase Uses

func NewCase(t *testing.T, name string) *T

NewCase wraps a testy.T struct around a testing.T struct. The resulting struct can be used in the same way the testing.T struct would be, plus has additional methods specific to Testy. It takes a name argument that is used in the summary line during log output.

func (*T) Done Uses

func (t *T) Done() string

Done returns any test log output formatted suitably for passing to a testing.T struct Logf method.

func (*T) Equal Uses

func (t *T) Equal(got, want interface{})

Equal checks if its arguments are equal using reflect.DeepEqual. It is subject to all the usual limitations of that function. If the values are not equal, an error is logged and the 'got' and 'want' values are logged on subsequent lines for comparison.

func (*T) Error Uses

func (t *T) Error(args ...interface{})

Error is equivalent to Log followed by Fail

func (*T) Errorf Uses

func (t *T) Errorf(format string, args ...interface{})

Errorf is equivalent to Logf followed by Fail

func (*T) Fail Uses

func (t *T) Fail()

Fail marks the test as having failed.

func (T) FailCount Uses

func (t T) FailCount() int

FailCount returns the number of Fail, Error, Fatal or test helper failures recorded by the testy.T struct.

func (*T) FailNow Uses

func (t *T) FailNow()

FailNow marks the test as having failed and stops execution. It is subject to the same restrictions as FailNow from the testing package.

func (*T) Failed Uses

func (t *T) Failed() bool

Failed reports whether the test has been marked as having failed.

func (*T) False Uses

func (t *T) False(cond bool)

False checks if its argument is false; if true, it logs an error.

func (*T) Fatal Uses

func (t *T) Fatal(args ...interface{})

Fatal is equivalent to Log followed by FailNow

func (*T) Fatalf Uses

func (t *T) Fatalf(format string, args ...interface{})

Fatalf is equivalent to Logf followed by FailNow

func (T) Label Uses

func (t T) Label(s ...interface{}) *T

Label returns a testy.T struct that will prefix a label to all log messages. The label is constructed by concatenating arguments separated by a space (like fmt.Sprintln without the trailing space). A colon character and space will be added automatically

func (*T) Log Uses

func (t *T) Log(args ...interface{})

Log joins its arguments by spaces like fmt.Sprintln and records the result for later delivery by the Done method.

func (*T) Logf Uses

func (t *T) Logf(format string, args ...interface{})

Logf joins its arguments like fmt.Sprintf and records the result for later delivery by the Done method.

func (*T) Nil Uses

func (t *T) Nil(got interface{})

Nil checks if its argument is nil (literal or nil slice, map, etc.); if non-nil, it logs an error.

func (*T) NotNil Uses

func (t *T) NotNil(got interface{})

Nil checks if its argument is nil (literal or nil slice, map, etc.); if non-nil, it logs an error.

func (T) Output Uses

func (t T) Output() []string

Output returns a copy of the slice of log messages recorded by the testy.T struct.

func (*T) Skip Uses

func (t *T) Skip(args ...interface{})

Skip is equivalent to Log followed by SkipNow

func (*T) SkipNow Uses

func (t *T) SkipNow()

SkipNow marks the test as skipped and halts execution. It is subject to the same restrictions as SkipNow from the testing package.

func (*T) Skipf Uses

func (t *T) Skipf(format string, args ...interface{})

Skipf is equivalent to Logf followed by SkipNow

func (*T) Skipped Uses

func (t *T) Skipped() bool

Skipped reports whether the test was skipped.

func (*T) True Uses

func (t *T) True(cond bool)

True checks if its argument is true; if false, it logs an error.

func (*T) Unequal Uses

func (t *T) Unequal(got, want interface{})

Unequal inverts the logic of Equal but is otherwise similar.

func (T) Uplevel Uses

func (t T) Uplevel(depth int) *T

Uplevel returns a testy.T struct that will report log messages 'depth' frames higher up the call stack.

Package testy imports 9 packages (graph). Updated 2017-12-04. Refresh now. Tools for package owners.