testbox

package
v3.0.2 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2022 License: Apache-2.0 Imports: 7 Imported by: 2

Documentation

Overview

Package testbox provides the ability to run test logic that uses a subset of Go's testing.T methods either inside or outside the regular testing environment.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ShouldFail

func ShouldFail(t assert.TestingT, action func(TestingT)) bool

ShouldFail is a shortcut for running some action against a testbox.TestingT and asserting that it failed.

func ShouldFailAndExitEarly

func ShouldFailAndExitEarly(t assert.TestingT, action func(TestingT)) bool

ShouldFailAndExitEarly is the same as ShouldFail, except that it also asserts that the test was terminated early with FailNow.

Types

type LogItem

type LogItem struct {
	// Path identifies the level of test that failed or was skipped.
	Path TestPath

	// Message is the failure message or skip message, if any. It is the result of calling fmt.Sprintf
	// or Sprintln on the arguments that were passed to TestingT.Errorf or TestingT.Skip. If a test
	// failed without specifying a message, this is "".
	Message string
}

LogItem describes either a failed assertion or a skip that happened during SandboxTest.

type SandboxResult

type SandboxResult struct {
	// True if any failures were reported during SandboxTest.
	Failed bool

	// True if the test run with SandboxTest called Skip or SkipNow. This is only true if
	// the top-level TestingT was skipped, not any subtests.
	Skipped bool

	// All failures logged during SandboxTest, including subtests.
	Failures []LogItem

	// All tests that were skipped during SandboxTest, including subtests.
	Skips []LogItem
}

SandboxResult describes the aggregate test state produced by calling SandboxTest.

func SandboxTest

func SandboxTest(action func(TestingT)) SandboxResult

SandboxTest runs a test function against a TestingT instance that applies only to the scope of that test. If the function makes a failed assertion, marks the test as skipped, or forces an early exit with FailNow or SkipNow, this is reflected in the SandboxResult but does not affect the state of the regular test framework (assuming that this code is even executing within a Go test; it does not have to be).

The reason this uses a callback function parameter, rather than simply having the SandboxResult implement TestingT itself, is that the function must be run on a separate goroutine so that the sandbox can intercept any early exits from FailNow or SkipNow.

SandboxTest does not recover from panics.

See TestingT for more details.

type TestPath

type TestPath []string

TestPath identifies the level of test that failed or skipped. SandboxResult.Failures and SandboxResult.Skips use this type to distinguish between the top-level test that was run with SandboxTest and subtests that were run within that test with TestingT.Run(). A nil value means the top-level test; a single string element is the name of a subtest run from the top level with TestingT.Run(); nested subtests add an element for each level.

type TestingT

type TestingT interface {
	require.TestingT
	// Run runs a subtest with a new TestingT that applies only to the scope of the subtest. It is
	// equivalent to the same method in testing.T, except the subtest takes a parameter of type TestingT
	// instead of *testing.T.
	//
	// If the subtest fails, the parent test also fails, but FailNow and SkipNow on the subtest do not
	// cause the parent test to exit early.
	Run(name string, action func(TestingT))

	// Failed tells whether whether any assertions in the test have failed so far. It is equivalent to
	// the same method in testing.T.
	Failed() bool

	// Skip marks the test as skipped and exits early, logging a message. It is equivalent to the same
	// method in testing.T.
	Skip(args ...interface{})

	// SkipNow marks the test as skipped and exits early. It is equivalent to the same method in testing.T.
	SkipNow()
}

TestingT is a subset of the testing.T interface that allows tests to run in either a real test context, or a mock test scope that is decoupled from the regular testing framework (SandboxTest).

This may be useful in a scenario where you have a contract test that verifies the behavior of some unknown interface implementation. In order to verify that the contract test is reliable, you could create implementations that either adhere to the contract or deliberately break it, run the contract test against those, and verify that the test fails if and only if it should fail.

The reason this cannot be done with the Go testing package alone is that the standard testing.T type cannot be created from within test code; instances are always passed in from the test framework. Therefore, the contract test would have to be run against the actual *testing.T instance that belongs to the test-of-the-test, and if it failed in a situation when we actually wanted it to to fail, that would be incorrectly reported as a failure of the test-of-the-test.

To work around this limitation of the testing package, this package provides a TestingT interface that has two implementations: real and mock. Test logic can then be written against this TestingT, rather than *testing.T.

func RunContractTests(t *testing.T, impl InterfaceUnderTest) {
    runContractTests(testbox.RealTest(t))
}

func runContractTests(abstractT testbox.TestingT, impl InterfaceUnderTest) {
    assert.True(abstractT, impl.SomeConditionThatShouldBeTrueForTheseInputs(someParams))
    abstractT.Run("subtest", func(abstractSubT helpers.TestingT) { ... }
}

func TestContractTestFailureCondition(t *testing.T) {
    impl := createDeliberatelyBrokenImplementation()
    result := testbox.SandboxTest(func(abstractT testbox.TestingT) {
        runContractTests(abstractT, impl) })
    assert.True(t, result.Failed // we expect it to fail
    assert.Len(t, result.Failures, 1)
}

TestingT includes the same subsets of testing.T methods that are defined in the TestingT interfaces of github.com/stretchr/testify/assert and github.com/stretchr/testify/require, so all assertions in those packages will work. It also provides Run, Skip, and SkipNow. It does not support Parallel.

func RealTest

func RealTest(t *testing.T) TestingT

RealTest provides an implementation of TestingT for running test logic in a regular test context.

See TestingT for details.

Jump to

Keyboard shortcuts

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