Library / SDK
gotestyourself/gotest.tools avatar
gotestyourself/gotest.tools

gotest.tools fills the gaps the standard testing package leaves open

A collection of packages to augment the go testing package and support common patterns.

576 stars56 forksGoNOASSERTION

At a glance

What is it?
gotest.tools is a set of Go packages that sit next to the standard testing package rather than replacing it, covering assertions, temporary files and directory comparisons, golden files, running binaries, polling asynchronous state, environment variables and skips. It is a patterns library for Go tests, and its value is in the parts of the standard library that have no equivalent.
Who is it for?
Adopt gotest.tools when your Go test suite needs the same handful of patterns more than once, in particular comparing filesystem trees, freezing large expected output, running a binary and checking its output, or waiting for asynchronous state. Do not adopt it for a small project with a handful of table driven tests, where the standard library is enough, and do not mix its assertion package with another one in the same file.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 39 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Augmenting testing rather than replacing it

The project describes itself as a collection of packages to augment `testing` and support common patterns, and that word augment sets the scope. Nothing here competes with the standard testing package. There is no runner, no test discovery, no mocking framework in the usual sense. What the collection provides is the set of helpers that a test suite ends up writing by hand once the third project needs them.

The module path is `gotest.tools/v3`, so the major version is baked into the import path, and the documentation site is gotest.tools/v3. The module file declares `go 1.17`, and it has two direct dependencies, `github.com/google/go-cmp` at v0.6.0 and `golang.org/x/tools` at v0.24.1, with `golang.org/x/mod` and `golang.org/x/sync` as indirect requirements.

The release history shows a slow cadence, which is the sort of thing worth knowing before you depend on it. The tags are v3.5.2 from 2025-02-08, v3.5.1 from 2023-09-16 and v3.5.0 from 2023-06-30, and the last push was on 2026-09-14. The repository is not archived, and the licence is one GitHub cannot categorise, with the text in the `LICENSE` file, so that is a file to read before it enters a dependency list.

Seven packages, seven problems

The package list in the README is short enough to memorise, and each entry names a specific recurring problem.

`assert` compares values and fails the test when a comparison fails. `env` is for test code which uses environment variables. `fs` creates temporary files and compares a filesystem tree to an expected value. `golden` compares large multi-line strings against values frozen in golden files. `icmd` executes binaries and tests the output. `poll` tests asynchronous code by polling until a desired state is reached. `skip` skips a test and prints the source code of the condition used to skip the test.

The interesting entries are the last three. `poll` exists because the standard library has no way to wait for a condition, so every project writes its own timeout loop, and the value here is not the loop but the failure message when the timeout expires. `icmd` exists because testing a command line tool means running a binary and comparing its output, which is a different shape from comparing a returned value. `skip` is the smallest and the most useful, since a skipped test that does not say why is a skipped test nobody investigates.

The `fs` package does the same for directories that `golden` does for strings, comparing a whole tree rather than a single expected value.

Adding it to a module

The usage section is two blocks, one for the dependency and one for the import path.

With Go modules enabled:

code
$ go get gotest.tools/v3

and the import for the assertion package:

code
import "gotest.tools/v3/assert"

The `/v3` suffix appears in both, which is the usual Go modules convention for a module whose major version is above one, and it is worth noting because getting it wrong is a compile error rather than a resolution problem.

The repository layout mirrors the package structure, with `assert/`, `env/`, `fs/`, `golden/`, `icmd/`, `poll/` and `skip/` as top level directories, plus `internal/` for shared code, `x/` for experimental packages, `scripts/`, a `pkg.go` file for the package documentation, a `.golangci.yml` configuration, a `.codecov.yml` and CircleCI configuration in `.circleci/`.

So the packages are separate modules of convenience rather than one large dependency, and a project that only wants `poll` and `icmd` can import only those.

assert sits on go-cmp, and that is the whole difference

The direct dependency on `github.com/google/go-cmp` is the design decision behind the `assert` package, and it is what separates it from the standard library's comparison helpers.

The standard library offers `reflect.DeepEqual`, which answers whether two values are equal and nothing else. When they are not equal, it says so, and the reader is left to work out which field differs. go-cmp produces a structured diff of the mismatch, and an assertion layer on top of that can report the difference rather than just the failure.

That matters most for the value types that show up in Go tests, structs with unexported fields, slices of structs, maps with struct keys, and types that implement `Equal` or `Format`. A plain equality check on those either reports false without explanation or needs hand written comparison code for each type.

The practical caution is about mixing. If a test file uses `assert` from this project and another assertion library, the failure output a reader sees depends on which one ran, and the mental model of a test suite gets harder to hold. Pick one assertion package per codebase, which is the practice the package's own position implies even if the README does not spell it out.

Waiting for state and running binaries

Two of the packages address the parts of testing that the standard library leaves to you, and they are the strongest reason to take the collection.

`poll` tests asynchronous code by polling until a desired state is reached. In practice this is the timeout loop every project writes for itself, and the value of a shared implementation is in the failure message, which tells you what you were waiting for and how long you waited, instead of a bare test timeout with no context.

`icmd` executes binaries and tests the output. That is a different shape from calling a function and comparing the return value, and the awkward parts are the same awkward parts every time: the process writes to stdout and stderr, the exit code matters, the output may contain paths that differ per machine, and the command may need to run in a specific directory. A package that has already solved those is worth more than a helper that only wraps `exec.Command`.

Between them, these two cover the cases where a Go test stops being a pure unit test. Once a test executes a real binary or waits for a real condition, it is slower, it is more sensitive to the machine, and it is the kind of test that gets skipped under time pressure, which is exactly why the failure messages matter more here than elsewhere.

Files, fixtures and the mechanics of skipping

The remaining packages cover data on disk and test control.

`fs` creates temporary files and compares a filesystem tree to an expected value, which is what you need when the output of a program is a directory rather than a string. `golden` compares large multi-line strings against values frozen in golden files, which is the established way to review a large expected output in a diff rather than inside the test source. `env` is for test code which uses environment variables, and `skip` skips a test and prints the source code of the condition used to skip it.

That last detail is the one to dwell on. A skipped test in the standard library leaves you with a line number and nothing else. Here the skip condition's source is printed, so the reader can see the condition that was not met, which is the difference between a skip you can triage and one you delete.

The `golden` package also carries a habit worth adopting whatever else you take from this repository. When the expected value changes, the change is a diff in a file, reviewed like any other change, rather than an edit inside a test function where a reviewer has to notice which string moved. That is a workflow property, not an API property, and it is the part of `golden` that tends to survive even in projects that write their own golden file handling.

The related projects the README points at make the same point from a different direction, with `gotestsum`, a go test runner with custom output, and wiki pages on Go testing patterns and on test doubles and patching, described as zero-dependency patterns for organising test cases and for fakes, spies, stubs and mocks.

Editorial conclusion

Adopt gotest.tools when your Go test suite needs the same handful of patterns more than once, in particular comparing filesystem trees, freezing large expected output, running a binary and checking its output, or waiting for asynchronous state. Do not adopt it for a small project with a handful of table driven tests, where the standard library is enough, and do not mix its assertion package with another one in the same file. Verify first that your Go version satisfies the module requirement of 1.17 or newer, that the licence in the repository's LICENSE file is acceptable for your organisation, and that the version you take matches the one you read, since the most recent tag is v3.5.2 from 2025-02-08 while the last push was on 2026-09-14.

Frequently asked questions

What is gotest.tools and what does it add to the Go testing package?

It is a collection of packages that augment the standard `testing` package and support common patterns. The packages are assert for comparisons that fail the test, env for environment variables, fs for temporary files and filesystem tree comparison, golden for large multi-line strings, icmd for executing binaries, poll for asynchronous state and skip for skipping a test with its condition printed.

How do I add gotest.tools to a Go project?

With Go modules enabled you run `go get gotest.tools/v3` and then import the package you need, for example `import "gotest.tools/v3/assert"`. The major version is part of the module path, so the `/v3` suffix has to be present in both the dependency and the import.

What does the poll package in gotest.tools do?

It tests asynchronous code by polling until a desired state is reached, which is the timeout loop that projects otherwise write for themselves. The README also points at a companion wiki page on zero-dependency Go testing patterns for organising test cases.

What licence does gotest.tools use?

The repository metadata classifies the licence as one GitHub cannot categorise, and the terms are in the LICENSE file in the repository root, so that file is the one to read. The LICENSE file in the repository root is the document to read for your organisation.

Official sources

  1. gotestyourself/gotest.tools on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/gotestyourself-gotest-tools.svg)](https://hysenlabs.com/projects/gotestyourself-gotest-tools)

Was this useful?