Looking for an explanation, I seeing a positive but surprising behavior wrt my go unit test cache:
consider the below directory structure:
/foo_test.go
/testdata/foodata/foo.go
/testdata/bardata/bar.go
the unit test at foo_test.go
uses golang.org/x/tools/go/packages.Load to read package /testdata/foodata/foo.go
. It does not import testdata/foodata
.
running go test foo_test.go
more than once does not result in the test being re-run but rather the test result is cached, as expected. Modifying /testdata/bardata/bar.go
also does not result in the test being re-run, also as expected. But modifying /testdata/foodata/foo.go
does result in the cache being invalidated and the test being run again, against my expectations. Is there something special about golang.org/x/tools/go/packages.Load
that adds packages loaded through it to the package dependency list for the purpose of go test
cache analysis?
This is actually expected due to how go/packages.Load
works and how Go's test caching system operates.
When you use packages.Load
, it performs static analysis of the code and creates a dependency relationship between your test and the loaded package, even though you're not importing it directly through Go's standard import mechanism. This is because packages.Load
needs to parse and analyze the target files to provide information about them.
The Go test cache system is quite sophisticated in tracking dependencies. It doesn't just look at explicit imports in your source code, but also tracks:
In your case, when packages.Load
reads /testdata/foodata/foo.go
, it effectively tells the Go build system "this test depends on the contents of this file." This is why modifying foo.go
invalidates the cache.
The reason bar.go
doesn't trigger a cache invalidation is that it's never loaded or analyzed by your test - it's not in the dependency graph that packages.Load
creates.