/testeach

Simple test setup/teardown for Go tests

Primary LanguageGoApache License 2.0Apache-2.0

Go TestEach

testeach provides a simple mechanism for shared test setup/teardown for Go tests.

For each case, all that case's parents are re-run, such that their setup, teardown and assertions automatically apply to the case.

Variable scoping follows natural language rules, avoiding issues common in BDD frameworks with Before() functions.

Cases are registered using callbacks rather than reflection, avoiding the possibility of tests mistakenly being missed due to typos.

Build Status

Usage Example (v3)

See v3/example_test.go for more examples.

package my_test

import (
    "testing"
    testeach "github.com/devnev/testeach/v3"
)

func TestMyType(t *testing.T) {
    // Suite setup goes here (equivalent to SetupSuite/TeardownSuite functions in suite frameworks)
    harness := createHarness(t)
    // In Go 1.14+, harness may use t.Cleanup, making this defer unnecessary.
    defer harness.Destroy()

    s := testeach.NewSuite(&t)

    s.Case("with state", func() {
        // Test setup goes here (equivalent to SetupTest/TeardownTest functions in suite frameworks)
        stuff := setupState(t)
        defer func() {
          teardown(stuff)
        }()

        // Individual test cases. The names must be static and are used as the sub-test name to `t.Run`.
        s.Case("it does the thing", func() {
            // assert a thing
        })
        s.Case("it does something else", func() {
            // assert something else
        })
        s.Case("with a particular setup", func() {
          // Can have test calls within callbacks. All setup and teardown is re-run for every sub-test.
          s.Case("it does another thing", func() {
            // more asserts
          })
        })
    })
}

Usage Example (v2)

See v2/example_test.go for more examples.

package my_test

import (
    "testing"
    . "github.com/devnev/testeach/v2"
)

func TestMyType(t *testing.T) {
    // Suite setup goes here (equivalent to SetupSuite/TeardownSuite functions in suite frameworks)
    harness := createHarness(t)
    // In Go 1.14+, harness may use t.Cleanup, making this defer unnecessary.
    defer harness.Destroy()

    Case(&t, "with state", func() {
        // Test setup goes here (equivalent to SetupTest/TeardownTest functions in suite frameworks)
        stuff := setupState(t)
        defer func() {
          teardown(stuff)
        }()

        // Individual test cases. The names must be static and are used as the sub-test name to `t.Run`.
        Case(&t, "it does the thing", func() {
            // assert a thing
        })
        Case(&t, "it does something else", func() {
            // assert something else
        })
        Case(&t, "with a particular setup", func() {
          // Can have test calls within callbacks. All setup and teardown is re-run for every sub-test.
          Case(&t, "it does another thing", func() {
            // more asserts
          })
        })
    })
}

Usage Example (v1)

See example_test.go for more examples.

package my_test

import (
    "testing"
    . "github.com/devnev/testeach"
)

func TestMyType(t *testing.T) {
    // Suite setup goes here (equivalent to SetupSuite/TeardownSuite functions in suite frameworks)
    harness := createHarness(t)
    // In Go 1.14+, harness may use t.Cleanup, making this defer unnecessary.
    defer harness.Destroy()

    Start(t, func(t *testing.T) {
        // Test setup goes here (equivalent to SetupTest/TeardownTest functions in suite frameworks)
        stuff := setupState(t)
        defer func() {
          teardown(stuff)
        }()

        // Individual test cases. The names must be static and are used as the sub-test name to `t.Run`.
        Case(t, "it does the thing", func() {
            // assert a thing
        })
        Case(t, "it does something else", func() {
            // assert something else
        })
        Case(t, "with a particular setup", func() {
          // Can have test calls within callbacks. All setup and teardown is re-run for every sub-test.
          Case(t, "it does another thing", func() {
            // more asserts
          })
        })
    })
}