This is the nature of go test
: it builds a special runtime with addition code to execute (this is how it tracks code coverage).
If it isnt fast enough, you have two options:
1) use bash tooling to compile a list of packages (e.g. using ls
), and then execute them each individually in parallel. There exists many ways to do this in bash.
The problem with this approach is that the output will be interleaved and difficult to track down failures.
2) use the t.Parallel()
flag with each of your tests to allow the test runtime to execute in parallel. Since Go 1.5, go test
runs with GOMAXPROCS
set to the number of cores on your CPU which allows for concurrently running tests. Tests are still ran synchronously by default. You have to set the t.Parallel()
flag for each test, telling the runtime it is OK to execute this test in parallel.
The problem with this approach being that it assumes you followed best practices and have used SoC/decoupling, don't have global states that would mutate in the middle of another test, no mutex locks (or very few of them), no race condition issues (use -race
), etc.
--
Opinion: Personally, I setup my IDE to run gofmt
and go test -cover -short
on every Save. that way, my code is always formatted and my tests are run, only within the package I am in, telling me if something failed. The -cover
flag works with my IDE to show me the lines of code that have been tested versus not tested. The -short
flag allows me to write tests that I know will take a while to run, and within those tests I can check t.Short()
bool to see if I should t.Skip()
that test. There should be packages available for your favorite IDE to set this up (I did it in Sublime, VIM and now Atom).
That way, I have instant feedback within the package I m editing.
Before I commit the code, I then run all tests across all packages. Or, I can just have the C.I. server do it.
Alternatively, you can make use of the -short
flag and build tags
(e.g. go test -tags integration
) to refactor your tests to separate your Unit tests from Integration tests. This is how I write my tests:
test that are fast and can run in parallel <- I make these tests run by default with go test
and go test -short
.
slow tests or tests that require external components, I require addition input to run, like go test -tags integration
is required to run them. This pattern does not run the integration tests with a normal go test
, you have to specify the additional tag. I don't run the integration tests across the board either. That's what my CI servers are for.