Selectively Running Tests in Go

Selectively Running Tests in Go
Photo by Alexander Schimmeck / Unsplash

This should most likely be filed in "things I'll probably forget unless I write it down." This post covers how to selectively run a subset of tests in Go. This can be useful for running a single test, all tests with a certain naming convention in a project, etc.

Overview

Let's start with a really basic example. We have two packages: bar and foo. Each package has a file with the same name as the package, a unit test file, and an integration test file.

├── bar
│   ├── bar.go
│   ├── bar_integration_test.go
│   └── bar_test.go
├── foo
│   ├── foo.go
│   ├── foo_integration_test.go
│   └── foo_test.go
├── go.mod
└── go.sum

The test files in the bar and foo packages look similar to what the bar package contents look like below:

package bar

import (
	"testing"

	"github.com/stretchr/testify/suite"
)

type BarTestSuite struct {
	suite.Suite
}

func TestBarTestSuite(t *testing.T) {
	suite.Run(t, &BarTestSuite{})
}

func (s *BarTestSuite) Test() {
	s.True(true)
}
bar/bar_test.go
package bar

import (
	"testing"

	"github.com/stretchr/testify/suite"
)

type BarIntegrationTestSuite struct {
	suite.Suite
}

func TestBarIntegrationTestSuite(t *testing.T) {
	suite.Run(t, &BarIntegrationTestSuite{})
}

func (s *BarIntegrationTestSuite) Test() {
	s.True(true)
}
bar/bar_integration_test.go

Run All Tests

If you're looking to just run all the tests in your project, you can do this really easily with the following command:

go test ./... -v

This results in the following output:

=== RUN   TestBarIntegrationTestSuite
=== RUN   TestBarIntegrationTestSuite/Test
--- PASS: TestBarIntegrationTestSuite (0.00s)
    --- PASS: TestBarIntegrationTestSuite/Test (0.00s)
=== RUN   TestBarTestSuite
=== RUN   TestBarTestSuite/Test
--- PASS: TestBarTestSuite (0.00s)
    --- PASS: TestBarTestSuite/Test (0.00s)
PASS
ok      github.com/bgreeley/golang-integration-test/bar 0.213s
=== RUN   TestFooIntegrationTestSuite
=== RUN   TestFooIntegrationTestSuite/Test
--- PASS: TestFooIntegrationTestSuite (0.00s)
    --- PASS: TestFooIntegrationTestSuite/Test (0.00s)
=== RUN   TestFooTestSuite
=== RUN   TestFooTestSuite/Test
--- PASS: TestFooTestSuite (0.00s)
    --- PASS: TestFooTestSuite/Test (0.00s)
PASS
ok      github.com/bgreeley/golang-integration-test/foo 0.400s

The ./... shorthand means to run all of the tests in all of the folders in this project recursively.

The -v option shows more verbose output for which tests were run, which passed / failed, how much time passed, etc.

Run Tests in a Single Package

If you want to run the tests in a single package, you can use the following command:

go test ./bar/... -v

This results in the following output:

=== RUN   TestBarIntegrationTestSuite
=== RUN   TestBarIntegrationTestSuite/Test
--- PASS: TestBarIntegrationTestSuite (0.00s)
    --- PASS: TestBarIntegrationTestSuite/Test (0.00s)
=== RUN   TestBarTestSuite
=== RUN   TestBarTestSuite/Test
--- PASS: TestBarTestSuite (0.00s)
    --- PASS: TestBarTestSuite/Test (0.00s)
PASS
ok      github.com/bgreeley/golang-integration-test/bar 0.214s

Run Tests in a Single Test File

If you want to run the tests in a single test file, you can use the following command:

go test ./bar/bar_test.go -v

This results in the following output:

=== RUN   TestBarTestSuite
=== RUN   TestBarTestSuite/Test
--- PASS: TestBarTestSuite (0.00s)
    --- PASS: TestBarTestSuite/Test (0.00s)
PASS
ok      command-line-arguments  0.356s

Run a Specific Test

If you want to run the a specific test in a single test, you can use the following command:

go test ./bar/bar_test.go -run TestBarTestSuite -v 

This results in the following output:

=== RUN   TestBarTestSuite
=== RUN   TestBarTestSuite/Test
--- PASS: TestBarTestSuite (0.00s)
    --- PASS: TestBarTestSuite/Test (0.00s)
PASS
ok      command-line-arguments  0.229s

Run Similarly Named Tests Across Different Files

If you want to run similarly named tests across different files, you can use the following command:

go test ./... -run "^Test.*IntegrationTestSuite$" -v

This is handy if you have a test name pattern for all integration tests and want to run all of these at once.

This results in the following output:

=== RUN   TestBarIntegrationTestSuite
=== RUN   TestBarIntegrationTestSuite/Test
--- PASS: TestBarIntegrationTestSuite (0.00s)
    --- PASS: TestBarIntegrationTestSuite/Test (0.00s)
PASS
ok      github.com/bgreeley/golang-integration-test/bar 0.214s
=== RUN   TestFooIntegrationTestSuite
=== RUN   TestFooIntegrationTestSuite/Test
--- PASS: TestFooIntegrationTestSuite (0.00s)
    --- PASS: TestFooIntegrationTestSuite/Test (0.00s)
PASS
ok      github.com/bgreeley/golang-integration-test/foo 0.407s

If you're having trouble writing a pattern, you can use list instead of run to see which tests will execute for the given pattern. In our case, if we run:

go test ./... -list "^Test.*IntegrationTestSuite$" -v

This results in the following output:

TestBarIntegrationTestSuite
ok      github.com/bgreeley/golang-integration-test/bar 0.211s
TestFooIntegrationTestSuite
ok      github.com/bgreeley/golang-integration-test/foo 0.402s

There are a lot more ways to control what's being tested, how it's being tested, different formats the results can be published in, etc. I'll cover those in future posts to keep this one more focused.