testctx

package module
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Feb 7, 2025 License: Apache-2.0 Imports: 5 Imported by: 3

README

testctx

*testing.T with context.Context and middleware

Package testctx aims to represent what *testing.T might have looked like if context.Context existed at the time it was created.

The main benefit of joining these two packages is support for test middleware, which can greatly cut down on repetition (t.Parallel()) and allow for transparent test instrumentation.

differences from Go 1.24 t.Context()

Go 1.24 adds a t.Context() accessor which provides a context.Context that will be canceled when the test completes, just before t.Cleanup-registered funcs are executed. However, it does not provide any way to modify the context.

By contrast, this package provides both a t.Context() and a t.WithContext(ctx) for modifying the context that is passed to sub-tests, and additionally passes the t.Context() value as a ctx argument to tests.

Documentation

Overview

Package testctx provides a context-aware wrapper around testing.T and testing.B with support for middleware and context propagation. It aims to represent what *testing.T might have looked like if context.Context existed at the time it was created.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type B

type B = W[*testing.B]

B is a wrapper around *testing.B

type BenchFunc

type BenchFunc = RunFunc[*testing.B]

BenchFunc is a benchmark function that takes a context and B

type Logger added in v0.0.2

type Logger interface {
	Log(args ...any)
	Logf(format string, args ...any)
	Error(args ...any)
	Errorf(format string, args ...any)
}

Logger represents something that can receive test log messages

type Middleware

type Middleware[T Runner[T]] func(RunFunc[T]) RunFunc[T]

Middleware represents a function that can wrap a test function

func WithParallel

func WithParallel() Middleware[*testing.T]

WithParallel creates middleware that runs tests in parallel

func WithTimeout

func WithTimeout[T Runner[T]](d time.Duration) Middleware[T]

WithTimeout creates middleware that adds a timeout to the test context

type MiddlewareB added in v0.0.3

type MiddlewareB = Middleware[*testing.B]

MiddlewareB is a middleware function that takes a context and B

type MiddlewareT added in v0.0.3

type MiddlewareT = Middleware[*testing.T]

MiddlewareT is a middleware function that takes a context and T

type RunFunc

type RunFunc[T Runner[T]] func(context.Context, *W[T])

RunFunc represents a test function that takes a context and a wrapper

type Runner

type Runner[T testing.TB] interface {
	testing.TB
	Run(string, func(T)) bool
}

Runner is a constraint for types that support subtests/subbenchmarks

type T

type T = W[*testing.T]

T is a wrapper around *testing.T

type TestFunc

type TestFunc = RunFunc[*testing.T]

TestFunc is a test function that takes a context and T

type W

type W[T Runner[T]] struct {

	// we have to embed testing.TB to become a testing.TB ourselves,
	// since it has a private method
	testing.TB
	// contains filtered or unexported fields
}

W is a context-aware wrapper for test/benchmark types that supports middleware and context propagation

func New

func New[T Runner[T]](t T, middleware ...Middleware[T]) *W[T]

New creates a context-aware test wrapper. The wrapper provides:

  • Context propagation through test hierarchies
  • Middleware support for test instrumentation
  • Logging interception via WithLogger

The context is automatically canceled when the test completes. See Using() for details on middleware behavior.

func (*W[T]) BaseName

func (w *W[T]) BaseName() string

BaseName returns the name of the test without the full path prefix

func (*W[T]) Context

func (w *W[T]) Context() context.Context

Context returns the current context

func (*W[T]) Error

func (w *W[T]) Error(args ...any)

Error calls through to the underlying test/benchmark type and logs if a logger is set

func (*W[T]) Errorf

func (w *W[T]) Errorf(format string, args ...any)

Errorf calls through to the underlying test/benchmark type and logs if a logger is set

func (*W[T]) Fatal

func (w *W[T]) Fatal(args ...any)

Fatal calls through to the underlying test/benchmark type and logs if a logger is set

func (*W[T]) Fatalf

func (w *W[T]) Fatalf(format string, args ...any)

Fatalf calls through to the underlying test/benchmark type and logs if a logger is set

func (*W[T]) Log

func (w *W[T]) Log(args ...any)

Log calls through to the underlying test/benchmark type and logs if a logger is set

func (*W[T]) Logf

func (w *W[T]) Logf(format string, args ...any)

Logf calls through to the underlying test/benchmark type and logs if a logger is set

func (*W[T]) Run

func (w *W[T]) Run(name string, fn RunFunc[T]) bool

Run runs a subtest with the given name and function. The function will be wrapped by any middleware registered via Using() or New(), with middleware executing in the order described by Using().

func (*W[T]) RunSuite

func (w *W[T]) RunSuite(s any)

RunSuite runs all methods on s that match the test method pattern:

  • Name starts with "Test"
  • Takes (context.Context, *W[T]) parameters

For example:

type MySuite struct{}
func (s *MySuite) TestFoo(ctx context.Context, t *testctx.T) {}

func TestSuite(t *testing.T) {
    testctx.New(t).RunSuite(&MySuite{})
}

func (*W[T]) Skip

func (w *W[T]) Skip(args ...any)

Skip calls through to the underlying test/benchmark type and logs if a logger is set

func (*W[T]) Skipf

func (w *W[T]) Skipf(format string, args ...any)

Skipf calls through to the underlying test/benchmark type and logs if a logger is set

func (*W[T]) Unwrap

func (w *W[T]) Unwrap() T

Unwrap returns the underlying test/benchmark type

func (*W[T]) Using added in v0.0.2

func (w *W[T]) Using(m ...Middleware[T]) *W[T]

Using adds middleware to the wrapper. Middleware are executed in a nested pattern: the first middleware added becomes the outermost wrapper, the last middleware added becomes the innermost wrapper. For example:

t.Using(first, second, third)

Results in the execution order:

first {
    second {
        third {
            test
        }
    }
}

This pattern ensures that: 1. "before" middleware code executes from outside-in (first -> third) 2. The test executes 3. "after" middleware code executes from inside-out (third -> first)

This matches the behavior of other middleware systems like net/http handlers and allows middleware to properly wrap both the setup and cleanup of resources.

func (*W[T]) WithContext

func (w *W[T]) WithContext(ctx context.Context) *W[T]

WithContext creates a new wrapper with the given context

func (*W[T]) WithLogger added in v0.0.2

func (w *W[T]) WithLogger(l Logger) *W[T]

WithLogger returns a new wrapper with the given logger. The logger will receive copies of all test log messages (Log, Logf), errors (Error, Errorf), fatal errors (Fatal, Fatalf), and skip notifications (Skip, Skipf). This allows test output to be captured or redirected while still maintaining the original test behavior.

Directories

Path Synopsis
otelmw module
oteltest module

Jump to

Keyboard shortcuts

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