gtest

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Dec 12, 2019 License: MIT Imports: 5 Imported by: 0

README

GTest

Documentation goreportcard codecov CircleCI

Lightweight Golang test framework inspired by pytest.

GTest provides the following functionalities to help reduce boilerplate in test code:

  • Test grouping
  • Setup, Teardown hooks for test groups
  • BeforeEach, AfterEach hooks for tests
  • Fixture injection

See docs, example_test.go and gtest_test.go for examples.

Documentation

Overview

Package gTest provides the following functionalities to help reduce boilerplate in test code:

- Test grouping

- Setup, Teardown hooks for test groups

- BeforeEach, AfterEach hooks for tests

- Fixture injection

Tests are grouped using struct methods. Each test in a test group needs to be defined as a struct method with `SubTest` prefix. Test group struct needs to implement GTest interface.

Example of test grouping:

import (
  "strings"
  "testing"
  "github.com/houqp/gtest"
)

type SampleTests struct{}

func (s *SampleTests) Setup(t *testing.T)      {}
func (s *SampleTests) Teardown(t *testing.T)   {}
func (s *SampleTests) BeforeEach(t *testing.T) {}
func (s *SampleTests) AfterEach(t *testing.T)  {}

func (s *SampleTests) SubTestCompare(t *testing.T) {
  if 1 != 1 {
    t.FailNow()
  }
}

func (s *SampleTests) SubTestCheckPrefix(t *testing.T) {
  if !strings.HasPrefix("abc", "ab") {
    t.FailNow()
  }
}

func TestSampleTests(t *testing.T) {
  gtest.RunSubTests(t, &SampleTests{})
}

Any struct with Construct and Destruct method defined can be registered as a fixture. Fixtures are referenced using fixture struct field tags.

Example of fixture injection:

import (
  "io/ioutil"
  "os"
  "testing"
  "github.com/houqp/gtest"
)

type WorkDirFixture struct{}

// Construct can take other fixtures as input parameter as well
func (s WorkDirFixture) Construct(t *testing.T, fixtures struct{}) (string, string) {
  dir, err := ioutil.TempDir("", "gtest-fixture")
  assert.NoError(t, err)

  // First return value will be passed to test as fixture value, second return value
  // will be passed to Destruct as ctx for cleanup purpose if needed.
  return dir, dir
}

// type for second input parameter of Destruct needs to match second return value of
// Construct method
func (s WorkDirFixture) Destruct(t *testing.T, dir string) {
  os.RemoveAll(dir)
}

func init() {
  gtest.MustRegisterFixture("WorkDir", &WorkDirFixture{}, gtest.ScopeSubTest)
}

type SampleTests struct{}

func (s *SampleTests) Setup(t *testing.T)      {}
func (s *SampleTests) Teardown(t *testing.T)   {}
func (s *SampleTests) BeforeEach(t *testing.T) {}
func (s *SampleTests) AfterEach(t *testing.T)  {}

func (s *SampleTests) SubTestMultipleFixtures(t *testing.T, fixtures struct {
  DirPath string `fixture:"WorkDir"`
}) {
  info, err := os.Stat(fixtures.DirPath)
  if err != nil {
    t.FailNow()
    return
  }
}

func TestSampleTests(t *testing.T) {
  gtest.RunSubTests(t, &SampleTests{})
}

Note that you can pass fixtures to fixture's Construct method as well, making it possible to build fixtures using other fixtures in a nested fashion.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MustRegisterFixture

func MustRegisterFixture(name string, f interface{}, scope FixtureScope)

Register a fixture, panic if registration failed.

func RegisterFixture

func RegisterFixture(name string, f interface{}, scope FixtureScope) error

Register a fixture under a given name. A fixture needs to be registered before it can be used in tests or other fixtures.

func RunSubTests

func RunSubTests(t *testing.T, gt GTest)

Run a group of sub tests.

Types

type FixtureEntry

type FixtureEntry struct {
	Scope    FixtureScope
	Instance interface{}
}

func GetFixture

func GetFixture(name string) (FixtureEntry, bool)

type FixtureScope

type FixtureScope string
const (
	// ScopeSubTest fixture's value will be cached, so multiple reference in
	// the same subtest will result in the same cached value.
	//
	// Good usecase for this scope is injecting the same database transaction
	// used by all fixtures in a subtest.
	ScopeSubTest FixtureScope = "subtest"
	// ScopeCall fixture will return different value for each reference in fixtures struct.
	ScopeCall FixtureScope = "call"
)

type GTest

type GTest interface {
	// Setup is called before any subtest runs in a test group.
	Setup(t *testing.T)
	// Teardown is called after all subtests are completed in a test group.
	Teardown(t *testing.T)

	// BeforeEach is called before each subtest runs.
	BeforeEach(t *testing.T)
	// AfterEach is called after each subtest is completed.
	// A good use case is doing go routine leak check in this method.
	AfterEach(t *testing.T)
}

Subtests are grouped in struct that implements GTest interface. Each test should be implemented as a struct method with `SubTest` as prefix.

Jump to

Keyboard shortcuts

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