Documentation
¶
Overview ¶
Package testo is a modular testing framework built on top of testing.T. It is focused on suite based tests and has an extensive plugin system.
Quick Start ¶
A minimal working example looks like this:
package main
import (
"testing"
"github.com/ozontech/testo"
)
type T struct { *testo.T }
type Suite struct { testo.Suite[T] }
func (Suite) Test(t T) { t.Log("Hello, world!") }
func Test(t *testing.T) { testo.RunSuite(t, new(Suite)) }
Notice the `Test(t *testing.T)` - since RunSuite requires an instance of `testing.T` we must declare a regular go test first, and only inside it we will be able to actually call our Testo suite.
Index ¶
- func For[Suite suite[T], T CommonT](test func(Suite, T), options ...testoplugin.Option) struct{}
- func ForEach[Suite suite[T], T CommonT, P any](test func(Suite, T, P), options ...testoplugin.Option) struct{}
- func Options(options ...testoplugin.Option)
- func Reflect(t CommonT) testoreflect.Reflection
- func Run[T CommonT](t T, name string, f func(t T), options ...testoplugin.Option) bool
- func RunSuite[Suite suite[T], T CommonT](testingT TestingT, suite Suite, options ...testoplugin.Option) bool
- type CommonT
- type Suite
- type T
- func (t *T) Context() context.Context
- func (t *T) Deadline() (time.Time, bool)
- func (t *T) Error(args ...any)
- func (t *T) Errorf(format string, args ...any)
- func (t *T) Fail()
- func (t *T) FailNow()
- func (t *T) Failed() bool
- func (t *T) Fatal(args ...any)
- func (t *T) Fatalf(format string, args ...any)
- func (t *T) Log(args ...any)
- func (t *T) Logf(format string, args ...any)
- func (t *T) Name() string
- func (t *T) Parallel()
- func (*T) Plugin(testoplugin.Plugin, ...testoplugin.Option) testoplugin.Spec
- func (t *T) Setenv(key, value string)
- func (t *T) Skip(args ...any)
- func (t *T) SkipNow()
- func (t *T) Skipf(format string, args ...any)
- func (t *T) Skipped() bool
- func (t *T) TempDir() string
- type TestingT
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func For ¶
func For[Suite suite[T], T CommonT]( test func(Suite, T), options ...testoplugin.Option, ) struct{}
For applies static options (annotations) for a given test.
Test annotations is a slice of options to be passed for this test. Test annotations are available to plugins before running an actual test, thus enhancing test planning features.
Multiple annotation calls to the same test will append options.
testo.For(MySuite.TestFoo, someplugin.WithThis(...), otherplugin.WithThat(...)) testo.For((*Suite).TestFoo, myplugin.WithRetry())
NOTE: it returns an empty struct{} value to enable the following usage:
var _ = testo.For(MySuite.TestFoo, someplugin.WithSomeOption(true))
func (MySuite) TestFoo(t T) { ... }
That "var _ =" construction would not be possible otherwise. This is slightly less verbose than using an init function:
func init() {
testo.For(MySuite.TestFoo, someplugin.WithSomeOption(true))
}
func ForEach ¶
func ForEach[Suite suite[T], T CommonT, P any]( test func(Suite, T, P), options ...testoplugin.Option, ) struct{}
ForEach applies static options (annotations) for each case of a given parametrized test.
Similar to For, but for parametrized tests.
testo.ForEach(MySuite.TestFoo, someplugin.WithThis(...), otherplugin.WithThat(...)) testo.ForEach((*Suite).TestFoo, myplugin.WithRetry())
func Options ¶
func Options(options ...testoplugin.Option)
Options appends given options to the global options.
Global options are prepended to each RunSuite call.
func init() {
testo.Options(myplugin.OutputDir("..."))
}
func Reflect ¶
func Reflect(t CommonT) testoreflect.Reflection
Reflect returns meta information about given t.
You can reflect over any test by accessing its T instance:
func (Suite) TestFoo(t T) {
r := testo.Reflect(t)
// r stores Reflection struct.
}
Same logic applies for plugins. If a plugin embeds `*testo.T` it can call the same testo.Reflect function:
type Plugin struct{ *testo.T }
func (p *Plugin) Plugin(parent testoplugin.Plugin, options ...testoplugin.Options) testoplugin.Spec {
return testoplugin.Spec{
Hooks: testoplugin.Hooks{
BeforeEach: testoplugin.Hook{
Func: func() { testo.Reflect(p) }
}
}
}
}
func Run ¶
func Run[T CommonT]( t T, name string, f func(t T), options ...testoplugin.Option, ) bool
Run runs f as a subtest of t called name. It runs f in a separate goroutine and blocks until f returns or calls t.Parallel to become a parallel test. Run reports whether f succeeded (or at least did not fail before calling t.Parallel).
Run may be called simultaneously from multiple goroutines, but all such calls must return before the outer test function for t returns.
WARN: Running this function during t.Cleanup panics.
func RunSuite ¶
func RunSuite[Suite suite[T], T CommonT]( testingT TestingT, suite Suite, options ...testoplugin.Option, ) bool
RunSuite will run the tests under the given suite.
Test is defined as a suite method in the form of "TestXXX" or "Test" which accepts a single parameter of the same type as T passed to this function.
It also accepts options for the plugins which can be used to configure those plugins. See testoplugin.Option.
RunSuite reports whether all suite tests succeeded.
Types ¶
type CommonT ¶
type CommonT interface {
// contains filtered or unexported methods
}
CommonT is the interface common for all T derivatives.
type Suite ¶
type Suite[T CommonT] struct { // contains filtered or unexported fields }
Suite is the base suite that all user-defined suites must embed.
Suite may optionally provide hooks by implementing their methods:
- BeforeAll(T) - is called before all suite tests once.
- BeforeEach(T) - is called before each suite test. T is shared with an actual test.
- AfterEach(T) - is called after each suite test. T is shared with an actual test.
- AfterAll(T) - is called after all suite tests once.
Example:
type MySuite struct {
testo.Suite[MyT]
}
type T ¶
type T struct {
// contains filtered or unexported fields
}
T is a wrapper for testing.T. This is a core entity in testo and used as a testing.T replacement.
The common pattern is to embed it into new struct type:
type MyT struct {
*testo.T
*SomePlugin
}
Plugins can also optionally embed it - testo will automatically initialize it by sharing the same value as an actual currently running test's T.
type SomePlugin struct { *testo.T }
func (*T) Context ¶
Context returns a context that is canceled just before Cleanup-registered functions are called.
Cleanup functions can wait for any resources that shut down on context.Context.Done before the test completes.
func (*T) Deadline ¶
Deadline reports the time at which the test binary will have exceeded the timeout specified by the -timeout flag.
By default, the ok result is false if the -timeout flag indicates "no timeout" (0).
func (*T) Fail ¶
func (t *T) Fail()
Fail marks the function as having failed but continues execution.
func (*T) FailNow ¶
func (t *T) FailNow()
FailNow marks the function as having failed and stops its execution by calling runtime.Goexit (which then runs all deferred calls in the current goroutine). Execution will continue at the next test or benchmark. FailNow must be called from the goroutine running the test or benchmark function, not from other goroutines created during the test. Calling FailNow does not stop those other goroutines.
func (*T) Log ¶
Log formats its arguments using default formatting, analogous to Println, and records the text in the error log. For tests, the text will be printed only if the test fails or the -test.v flag is set. For benchmarks, the text is always printed to avoid having performance depend on the value of the -test.v flag.
func (*T) Logf ¶
Logf formats its arguments according to the format, analogous to Printf, and records the text in the error log. A final newline is added if not provided. For tests, the text will be printed only if the test fails or the -test.v flag is set. For benchmarks, the text is always printed to avoid having performance depend on the value of the -test.v flag.
func (*T) Name ¶
Name returns the name of the running (sub-) test or benchmark.
The name will include the name of the test along with the names of any nested sub-tests. If two sibling sub-tests have the same name, Name will append a suffix to guarantee the returned name is unique.
func (*T) Parallel ¶
func (t *T) Parallel()
Parallel signals that this test is to be run in parallel with (and only with) other parallel tests. When a test is run multiple times due to use of -test.count or -test.cpu, multiple instances of a single test never run in parallel with each other.
func (*T) Plugin ¶
func (*T) Plugin(testoplugin.Plugin, ...testoplugin.Option) testoplugin.Spec
Plugin implements testoplugin.Plugin.
This is a placeholder to prevent other .Plugin methods being promoted.
func (*T) Setenv ¶
Setenv calls os.Setenv(key, value) and uses Cleanup to restore the environment variable to its original value after the test.
Because Setenv affects the whole process, it cannot be used in parallel tests or tests with parallel ancestors.
func (*T) SkipNow ¶
func (t *T) SkipNow()
SkipNow marks the test as having been skipped and stops its execution by calling runtime.Goexit. If a test fails (see Error, Errorf, Fail) and is then skipped, it is still considered to have failed. Execution will continue at the next test or benchmark. See also FailNow. SkipNow must be called from the goroutine running the test, not from other goroutines created during the test. Calling SkipNow does not stop those other goroutines.
func (*T) TempDir ¶
TempDir returns a temporary directory for the test to use. The directory is automatically removed when the test and all its subtests complete. Each subsequent call to t.TempDir returns a unique directory; if the directory creation fails, TempDir terminates the test by calling Fatal.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
internal
|
|
|
pragma
Package pragma provides types that can be embedded into a struct to statically enforce or prevent certain language properties.
|
Package pragma provides types that can be embedded into a struct to statically enforce or prevent certain language properties. |
|
testnamer
Package testnamer copies test naming functionality as seen in go test.
|
Package testnamer copies test naming functionality as seen in go test. |
|
Package testocache provides caching primitives to be used by external plugins.
|
Package testocache provides caching primitives to be used by external plugins. |
|
Package testoplugin provides plugin primitives for using plugins in testo.
|
Package testoplugin provides plugin primitives for using plugins in testo. |
|
Package testoreflect provides reflection primitives for T.
|
Package testoreflect provides reflection primitives for T. |
