Go言語のパッケージのテストでプライベートな関数や変数を呼び出すには
Go言語でパッケージのテストを書く時に、プライベートな関数(隠蔽した関数)や定数を呼び出したいことがたまにあります。 これを実現する方法をメモ。
プライベートって?
パッケージの内容は以下のような構成になっているとします:
- eg.go
- eg_test.go
ここで:
eg.go:
package eg import () func foo() string { return "foo" }
という実装があります。関数名のはじまりを小文字foo
にし、意図的に関数を外部から隠蔽しています。これでプライベートになります。(というか、基本は小文字で隠蔽し、公開したい場合は大文字にするといった使い方になるはずです)
さて、テストコードから隠蔽したメソッドを呼ぶにはどうしたらいいでしょう。
関数名のはじまりを大文字にし、Foo
として公開(エクスポート)したくなります。が、公開する必要がないのに公開する(またはテストのためだけに公開する)のは設計として問題があります。
解決策:
eg.go
と同一パッケージ名(ここではeg
)を使用した、export_test.go
を追加します。ファイルの名称は自由ですが、Goの基本パッケージ内でよく使われているため、この名称を利用しています(ただし、_test.go
をつけてテスト対象のファイルであることを明示する必要があります)。
この中の実装は:
export_test.go:
package eg var FooA = fooA
とします。これは、eg.go
内のfooA
の関数ポインタをFooA
という公開した変数へ代入しています。
つまり、これで公開したことになります。
もちろん、このコードはテスト専用ですので、APIとして公開されることはありません。
それでは、テストコードを書いてみましょう:
eg_test.go:
package eg_test import ( . "." "testing" ) func TestFunc(t *testing.T) { result := Foo() if result != "foo" { t.Errorf("result = %v, want %v", result, "foo") } }
結果は:
$ go test PASS ok
となり、ちゃんと呼び出すことができました。
また、同じようにして、内部変数も参照できます:
eg.go:
const ( max = '\U0010FFFF' // Maximum value )
export_test.go:
const ( Max = max )
おわりに:
っと、書きましたが、内部のテストを細かく書くよりも公開したAPIを利用するテストを充実させ、リファクタリングに対応できるように心がけたいです。
ここで挙げたコードのサンプルを作ってみましたので、参考にどうぞ: