プログラミングメモ.txt

プログラミングに関する技術のメモです。

Goのテストでプライベートの値を参照できずハマった話

Goのテストをする際にプライベートな値などを参照するためにexport_test.goといったファイルを作って、テストコードからのみ参照できるようにするテクニックがあります。

このテクニックについては次の記事がわかりやすいので知らない方はまずそちらを参照することをおすすめします。

engineering.mercari.com

しかし、このテクニックを使ったにも関わらずテストコード上からプライベートな値を参照できないという事態に遭遇しました。

サンプルコード

// hoge/hoge.go
package hoge

const fuga = 1
// hoge/export_test.go
package hoge

const Fuga = fuga
// hoge/hoge_test.go
package hoge_test

import (
    "fmt"
    "testing"

    "github.com/nijinekko/blog/samples/invalidexporttest/hoge"
)

func TestFuga(t *testing.T) {
    if hoge.Fuga != 1 {
        t.Error(fmt.Errorf("want 1, but got %v", hoge.Fuga))
    }
}
// main.go
package main

func main() {
}
// main_test.go
package main

import (
    "fmt"
    "testing"

    "github.com/nijinekko/blog/samples/invalidexporttest/hoge"
)

func TestMain(t *testing.T) {
    if hoge.Fuga != 1 {
        t.Error(fmt.Errorf("want 1, but got %v", hoge.Fuga))
    }
}

これらのコードでgo testを実行するとhoge_test.goでは、hoge.Fugaが参照できますが、main_test.goではhoge.Fugaが参照できずビルドエラーになります。

サンプルコードの全体はこちら

原因

go help test を見てみると次のような記述があります。

'Go test' recompiles each package along with any files with names matching the file pattern "*_test.go".

Each listed package causes the execution of a separate test binary.

パッケージ毎にテストバイナリが作成されるため、mainパッケージのコンパイル時にはexport_test.goが見えないようです。