75
votes

Is it possible to skip/exclude some tests from being run with go test?

I have a fairly large amount of integration type tests which call a rest service written as standard go tests, and run with go test. When a new feature is developed its sometimes useful to be able to skip some of the tests, for example if the new feature is not yet deployed on the testing server and I still want to run all the existing tests (except those new ones which tests the new feature).

I know about -run, but I dont want to specify all tests I want to run, that would be a long list. At the same time I have not been able to write a regex for excluding tests.

Another option would be to not commit the tests which dont run in the same branch, but it would be easier if I could just specify what to exclude.

3
You could specify the tests as either long or short and then run only the short ones unless all are required. golang.org/pkg/testing - Intermernet
Thats one way to do it, but it means that I need to update the test code once the new feature is deployed on the testing server. Feels wrong to need to add specific code to handle if a feature is deployed or not - viblo
split the tests into different _test files ? - fabrizioM
I dont understand how different _test files would help (but yes, I already have many _test files)? I would still need to list all the _test files except the one to exclude, right? - viblo
Sometimes for integration tests I have it check for an environment variable; if set, it runs them. Otherwise it doesn't. - Matt

3 Answers

102
votes

Testing package has SkipNow() and Skip() methods. So, an individual test could be prepended with something like this:

func skipCI(t *testing.T) {
  if os.Getenv("CI") != "" {
    t.Skip("Skipping testing in CI environment")
  }
}

func TestNewFeature(t *testing.T) {
  skipCI(t)
}

You could then set the environment variable or run CI=true go test to set CI as a command-local variable.

Another approach would be to use short mode. Add the following guard to a test

if testing.Short() {
  t.Skip("skipping testing in short mode")
}

and then execute your tests with go test -short

62
votes

Like VonC said, you can use +build tags

┌─ oneofone@Oa [/t/tst-tag]                                                                                                      
└──➜ ls
a_test.go  b_test.go  c_test.go

a_test.go :

package tags

import "testing"

func TestA(t *testing.T) {}

b_test.go :

// +build !feature1

package tags

import "testing"

func TestB(t *testing.T) {}

c_test.go :

// +build !feature1
// +build !feature2

package tags

import "testing"

func TestC(t *testing.T) {}

Then run the test with the -tags parameter :

┌─ oneofone@Oa [/t/tst-tag]                                                                                                      
└──➜ go test -v . | grep PASS:
--- PASS: TestA (0.00 seconds)
--- PASS: TestB (0.00 seconds)
--- PASS: TestC (0.00 seconds)
┌─ oneofone@Oa [/t/tst-tag]                                                                                                      
└──➜ go test -v -tags feature1 . | grep PASS:
--- PASS: TestA (0.00 seconds)
┌─ oneofone@Oa [/t/tst-tag]                                                                                                      
└──➜ go test -v -tags feature2 . | grep PASS:
--- PASS: TestA (0.00 seconds)
--- PASS: TestB (0.00 seconds)

// Update : different logic :

a_test.go:

// +build all

package tags

import "testing"

func TestA(t *testing.T) {}

b_test.go:

// +build all feature1

package tags

import "testing"

func TestB(t *testing.T) {}

c_test.go:

// +build all feature2

package tags

import "testing"

func TestC(t *testing.T) {}


┌─ oneofone@Oa [/t/tst-tag]                                                                                                      
└──➜ go test -v -tags all | grep PASS:
--- PASS: TestA (0.00 seconds)
--- PASS: TestB (0.00 seconds)
--- PASS: TestC (0.00 seconds)
┌─ oneofone@Oa [/t/tst-tag]                                                                                                      
└──➜ go test -v -tags feature1 | grep PASS:
--- PASS: TestB (0.00 seconds)
┌─ oneofone@Oa [/t/tst-tag]                                                                                                      
└──➜ go test -v -tags="feature1 feature2" | grep PASS:
--- PASS: TestB (0.00 seconds)
--- PASS: TestC (0.00 seconds)

Or you call specific tests by name like :

d_test.go:

package tags

import "testing"

func TestA1(t *testing.T) {}
func TestB1(t *testing.T) {}
func TestC1(t *testing.T) {}
func TestD1(t *testing.T) {}

Output:

┌─ oneofone@Oa [/t/tst-tag]                                                                                                      
└──➜ go test -run="(A|B)1" -v | grep PASS:
--- PASS: TestA1 (0.00 seconds)
--- PASS: TestB1 (0.00 seconds)
┌─ oneofone@Oa [/t/tst-tag]                                                                                                      
└──➜ go test -run="D1" -v | grep PASS:
--- PASS: TestD1 (0.00 seconds)
3
votes

Supplement to the Vadym Tyemirov's answer.

You can use TestMain skip test in whole pkg when env CI not empty.

func TestMain(m *testing.M) {
    if os.Getenv("CI") == "" {
        m.Run()
    }
}