Go Test Files Are Part of the Same Package

Just a quick one. I was working on improving performance for a certain method of mine. I had found the hot loop * pprof is an amazing godsend. The days of dicking around in valgrind or cProfile are long a memory of the past , and I wrote a few benchmark methods to test some ideas.

I was using the testing package’s benchmark function to benchmark the methods, and for a method, I had abstracted out some code so that it can run in a goroutine. Here’s the code for the function:


func receiver(ch chan tmp, out chan []float64, wg *sync.WaitGroup) {
    Ys := make([]float64, len(x))
    for v := range ch {
        Ys[v.id] = v.res
        wg.Done()
    }
    out <- Ys
}

Spotted the problem? No? It’s the second line: retVal := make([]float64, len(x)). You’ll note that x wasn’t declared anywhere. And yet, the benchmarks ran! I only ran into a problem when I fed the test case a weird corner case where I knew funny things would happen.

At first I was puzzled why the compiler hadn’t caught it. I scoured all through both files (it was a throwaway package, written solely to test ideas, so it had only two files: throwaway.go and throwaway_test.go)

Here are the top few lines of my throwaway_test.go file:


package throwaway

import (
    "testing"
    "math/rand"
)

var x []float64 = X(784) // <-- THE DECLARATION THAT CAUSED PAIN
func init() { ... }

I had added that variable originally as part of a setup/teardown function. I had then forgotten completely about it. I had been so used to writing code in the *_test.go files as if they were part of a separate package that just imported the functions, that I forgot that they were part of the same package.

The lesson learned today, other than global variables are evil* but sometimes are necessary, which I would argue for this specific test case, is , is that variables declared in the test files can have an effect on the main files if you’re not careful about it, because the test files are part of the same package.

Now I want my hour lost back!

Adddendum

As Damian kindly points out:

The above only really happened because I was running go test -bench . a lot. If I had used go build . the compiler would have thrown an error

comments powered by Disqus