-
Notifications
You must be signed in to change notification settings - Fork 18.5k
Description
It is a common pattern to want to run Go tests in sequence rather than in parallel. Within a package, this is controlled by t.Parallel() and -test.parallel. However, across packages there is a different control: -p N (typically -p 1 for this use case).
This is commonly used for integration tests which are depending on exclusive access to some resource outside of the test.
However, this comes at a huge cost: -p 1 does not control just test parallelism, but all compiler actions. This means all compiling and linking is done sequentially. In our project, this has caused a 10x increase in test execution times - with -p 1, it takes 8m25s; without, 50s.
I would like a way to run test packages sequentially, while still benefiting from the parallelism in building.
Ecosystem usage
I did a rough analysis of usage of go test -p 1 across Github, and found a number of large projects doing the same. I use stars just as a rough measure of the project scope.
If you search "go run tests sequentually", basically all sources will tell you to use -p 1. This includes AI chatbots, popular stack overflow answers, blogs, and even some Go core maintainer recommendations.
Alternatives
- Run multiple Go commands (such as
go test ./a && go test ./b). This is not great; we lose parallelism in building. - Pre-build all the binaries (such as
go test -c -o tests/ ./...; go test -p 1 ./...). This is demonstrated as effective here. However, it is highly limited unless proposal: cmd/go: support naming compiled tests with full qualified name #61199 is resolved as well. - Pre-compile only the binaries, demonstrated here. Basically we warm the build cache. This is better than nothing, but still much worse due to linking done sequentially. In our project, naive approach is 8min, this is 4min, while optimal is ~50s.
- Put synchronization into the test binary itself. This is challenging and ineffective. Things like mutex cannot be used as it is cross-binary, so we need an external locking system. Even with that, it isn't effective. Tests will start and wait, blocking a worker. This results in something similar to this issue, which showed at least 2x worse test times.
- Rework the tests to use one package or allow parallel execution. This is great if you can, but its a big ask.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status