Testing unexported identifiers in Go
In order to minimise the surface area for testing a common practice is to focus
testing only on the public API of a package, placing all the tests is a _test
package.
For example, consider a simple math
package with an exported function Square
.
package math
func Square(a int) int {
return a * a
}
Tests for this might look like so...
package math_test
import (
"testing"
"path.to/math"
)
func TestSquare(t *testing.T) {
if result := Square(2); result != 4 {
t.Errorf("Exected Square(2) to equal 4 but got %d", result)
}
}
This is great, until you want to write some specific tests for an unexported
identifier. Imagine we add a multiply
function that we want to test directly
alongside our existing tests.
package math
func Square(a int) int {
return multiply(a,a)
}
func multiply(a, b int) int {
return a * b
}
Because the multiply
function is unexported we cannot access it in the
math_test
package. What we can do however, is make this function exported
only when running tests. To do this, we add a new file export_test.go
that exports the multiply
function in the math
package.
package math
var Multiply = multiply
We can now write tests that use this exported identifier instead 🎉
package math_test
import (
"testing"
"path.to/math"
)
func TestSquare(t *testing.T) {
if result := math.Square(2); result != 4 {
t.Errorf("Exected Square(2) to equal 4 but got %d", result)
}
}
func TestMultiply(t *testing.T) {
if result := math.Multiply(1, 2); result != 2 {
t.Errorf("Exected Multiply(1, 2) to equal 2 but got %d", result)
}
}