Skip to content

testing: add Cleanup method #32111

Closed
Closed
@rogpeppe

Description

@rogpeppe

It's a common requirement to need to clean up resources at the end of a test - removing temporary directories, closing file servers, etc.

The standard Go idiom is to return a Closer or a cleanup function and defer a call to that, but in a testing context, that can be tedious and add cognitive overhead to reading otherwise simple test code. It is useful to be able to write a method that returns some domain object that can be used directly without worrying the caller about the resources that needed to be created (and later destroyed) in order to provide it.

Some test frameworks allow tear-down methods to be defined on "suite" types, but this does not compose well and doesn't feel Go-like.

Instead, I propose that we add a Defer method to the testing.B, testing.T and testing.TB types that will register a function to be called at the end of the test.

The implementation could be something like this:

type T struct {
	// etc
	mu sync.Mutex
	deferred func()
}

// Defer registers a function to be called at the end of the test.
// Deferred functions will be called in last added, first called order.
func (t *T) Defer(f func()) {
	t.mu.Lock()
	defer t.mu.Unlock()
	oldDeferred := t.deferred
	t.deferred = func() {
		defer oldDeferred()
		f()
	}
}

// done calls all the functions registered by Defer in reverse
// registration order.
func (t *T) done() {
	t.mu.Lock()
	deferred := t.deferred
	t.mu.Unlock()

	deferred()
}

The quicktest package uses this approach and it seems to work well.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions