gunit

package module
v1.4.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 3, 2023 License: MIT Imports: 9 Imported by: 0

README

SMARTY DISCLAIMER: Subject to the terms of the associated license agreement, this software is freely available for your use. This software is FREE, AS IN PUPPIES, and is a gift. Enjoy your new responsibility. This means that while we may consider enhancement requests, we may or may not choose to entertain requests at our sole and absolute discretion.

Build Status Code Coverage Go Report Card GoDoc

gunit

Installation

$ go get github.com/smartystreets/gunit

We now present gunit, yet another testing tool for Go.

Not again... (GoConvey was crazy enough...but sort of cool, ok I'll pay attention...)

No wait, this tool has some very interesting properties. It's a mix of good things provided by the built-in testing package, the assertions you know and love from the GoConvey project, the xUnit testing style (the first real unit testing framework), and it's all glued together with go test.

Blah, blah, yeah, yeah. Ok, so what's wrong with just using the standard "testing" package? What's better about this gunit thing?

The convention established by the "testing" package and the go test tool only allows for local function scope:

func TestSomething(t *testing.T) {
	// blah blah blah
}

This limited scope makes extracting functions or structs inconvenient as state will have to be passed to such extractions or state returned from them. It can get messy to keep a test nice and short. Here's the basic idea of what the test author using gunit would implement in a *_test.go file:


package examples

import (
    "time"
	"testing"

	"github.com/smartystreets/assertions/should"
	"github.com/smartystreets/gunit"
)

func TestExampleFixture(t *testing.T) {
	gunit.Run(new(ExampleFixture), t)
}

type ExampleFixture struct {
	*gunit.Fixture // Required: Embedding this type is what makes the magic happen.

	// Declare useful state here (probably the stuff being tested, any fakes, etc...).
}

func (this *ExampleFixture) SetupStuff() {
	// This optional method will be executed before each "Test"
	// method (because it starts with "Setup").
}
func (this *ExampleFixture) TeardownStuff() {
	// This optional method will be executed after each "Test"
	// method (because it starts with "Teardown"), even if the test method panics.
}


// This is an actual test case:
func (this *ExampleFixture) TestWithAssertions() {
	// Here's how to use the functions from the `should`
	// package at github.com/smartystreets/assertions/should
	// to perform assertions:
	this.So(42, should.Equal, 42)
	this.So("Hello, World!", should.ContainSubstring, "World")
}

func (this *ExampleFixture) SkipTestWithNothing() {
	// Because this method's name starts with 'Skip', it will be skipped.
}

func (this *ExampleFixture) LongTestSlowOperation() {
	// Because this method's name starts with 'Long', it will be skipped if `go test` is run with the `short` flag.
	time.Sleep(time.Hour)
	this.So(true, should.BeTrue)
}

So, I see just one traditional test function and it's only one line long. What's the deal with that?

Astute observations. gunit allows the test author to use a struct as the scope for a group of related test cases, in the style of xUnit fixtures. This makes extraction of setup/teardown behavior (as well as invoking the system under test) much simpler because all state for the test can be declared as fields on a struct which embeds the Fixture type from the gunit package. All you have to do is create a Test function and pass a new instance of your fixture struct to gunit's Run function along with the *testing.T and it will run all defined Test methods along with the Setup and Teardown method.

Enjoy.

Parallelism

By default all fixtures are run in parallel as they should be independent, but if you for some reason have fixtures which need to be run sequentially, you can change the Run() method to RunSequential(), e.g. in the above example

func TestExampleFixture(t *testing.T) {
	gunit.RunSequential(new(ExampleFixture), t)
}

Advanced Examples


For users of JetBrains IDEs, here's LiveTemplate you can use for generating the scaffolding for a new fixture:

  • Abbreviation: fixture
  • Description: Generate gunit Fixture boilerplate
  • Template Text:
func Test$NAME$(t *testing.T) {
    gunit.Run(new($NAME$), t)
}

type $NAME$ struct {
    *gunit.Fixture
}

func (this *$NAME$) Setup() {
}

func (this *$NAME$) Test$END$() {
}

Be sure to specify that this LiveTemplate is applicable in Go files.

Documentation

Overview

Package gunit provides "testing" package hooks and convenience functions for writing tests in an xUnit style. See the README file and the examples folder for examples.

Index

Constants

This section is empty.

Variables

View Source
var Options singleton

Functions

func Run

func Run(fixture any, t *testing.T, options ...option)

Run receives an instance of a struct that embeds *Fixture. The struct definition may include Setup*, Teardown*, and Test* methods which will be run as an xUnit-style test fixture.

func RunSequential

func RunSequential(fixture any, t *testing.T)

RunSequential (like Run) receives an instance of a struct that embeds *Fixture. The fixture is run in much the same way, except that it will not be run in parallel with other fixtures in the same package, nor will test cases of the corresponding fixture be run in parallel with each other.

Deprecated

Use Run(fixture, t, Options.AllSequential()) instead.

Types

type Fixture

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

Fixture keeps track of test status (failed, passed, skipped) and handles custom logging for xUnit style tests as an embedded field. The Fixture manages an instance of *testing.T. Certain methods defined herein merely forward to calls on the *testing.T:

  • Fixture.Error(...) ----> *testing.T.Error
  • Fixture.Errorf(...) ---> *testing.T.Errorf
  • Fixture.Print(...) ----> *testing.T.Log or fmt.Print
  • Fixture.Printf(...) ---> *testing.T.Logf or fmt.Printf
  • Fixture.Println(...) --> *testing.T.Log or fmt.Println
  • Fixture.Failed() ------> *testing.T.Failed()
  • Fixture.fail() --------> *testing.T.Fail()

We don't use these methods much, preferring instead to lean heavily on Fixture.So and the rich set of should-style assertions provided at github.com/smartystreets/assertions/should

func (*Fixture) Assert

func (this *Fixture) Assert(condition bool, messages ...string) bool

Assert tests a boolean which, if not true, marks the current test case as failed and prints the provided message.

func (*Fixture) AssertDeepEqual

func (this *Fixture) AssertDeepEqual(expected, actual any) bool

func (*Fixture) AssertEqual

func (this *Fixture) AssertEqual(expected, actual any) bool

func (*Fixture) AssertSprintEqual

func (this *Fixture) AssertSprintEqual(expected, actual any) bool

func (*Fixture) AssertSprintfEqual

func (this *Fixture) AssertSprintfEqual(expected, actual any, format string) bool

func (*Fixture) Error

func (this *Fixture) Error(args ...any)

func (*Fixture) Errorf

func (this *Fixture) Errorf(f string, args ...any)

func (*Fixture) Failed

func (this *Fixture) Failed() bool

func (*Fixture) Name

func (this *Fixture) Name() string

func (*Fixture) Print

func (this *Fixture) Print(a ...any)

func (*Fixture) Printf

func (this *Fixture) Printf(format string, a ...any)

func (*Fixture) Println

func (this *Fixture) Println(a ...any)

func (*Fixture) Run added in v1.3.5

func (this *Fixture) Run(name string, test func(fixture *Fixture))

Run is analogous to *testing.T.Run and allows for running subtests from test fixture methods (such as for table-driven tests).

func (*Fixture) So

func (this *Fixture) So(actual any, assert assertion, expected ...any) bool

So is a convenience method for reporting assertion failure messages, from the many assertion functions found in github.com/smartystreets/assertions/should. Example: this.So(actual, should.Equal, expected)

func (*Fixture) T added in v1.1.0

func (this *Fixture) T() TestingT

T exposes the TestingT (*testing.T) instance.

func (*Fixture) Write

func (this *Fixture) Write(p []byte) (int, error)

Write implements io.Writer. There are rare times when this is convenient (debugging via `log.SetOutput(fixture)`).

type TestingT added in v1.1.0

type TestingT interface {
	Helper()
	Name() string
	Log(args ...any)
	Fail()
	Failed() bool
	Fatalf(format string, args ...any)
	Errorf(format string, args ...any)
}

TestingT represents the functional subset from *testing.T needed by Fixture.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL