Go でテストを書くとき、private 定義しているものの扱いについてちょっとしたコツです。
目次
Goでのpublic/private
Go では変数名や関数名などの先頭が大文字だと public、小文字だと private となります。
↓ こんな感じ。
var PublicVariable string = "publicな変数です。" var privateVariable string = "privateな変数です。"
異なるパッケージから、参照するためには、public で定義する必要があります。
Goでは、同一パッケージのファイルは同一ディレクトリに配置するのですが、テストパッケージは例外でテスト対象パッケージと同一ディレクトリに配置します。
しかし、あくまでテストパッケージとテスト対象パッケージは別パッケージです。
つまり、テストパッケージから、テスト対象パッケージ内で定義されたものを参照したい場合 public である必要があるわけです。
ただ、元の実装として private としているものをテストのためだけに public にするのは微妙です。
なので対処法を書いておきます。
export_test.go
まずは export_test.go
というファイルを用意します。_test.go
とついていますが、export_test.go
のパッケージはテストパッケージではなく、テスト対象パッケージとします。 ここでは、pkg
。
├── main.go └── pkg ├── export_test.go ├── pkg.go └── pkg_test.go
Goではxxx_test.go
という命名のファイルはgo build
のビルド対象に入りません。go test
でのみビルドされます。
こうすることで、pkgパッケージ内のprivateなものを参照可能で、テスト時以外ビルドされないファイルとなります。
このファイルの中で private のものを public で定義し直していきます。
変数, 定数
// pkg.go package pkg var variable string = "プライベートな変数" const constant string = "プライベートな定数"
// export_test.go package pkg var Variable = variable const Constant = constant
先頭大文字で定義する。
関数
// pkg.go package pkg func fn(s string) error { // do something }
// export_test.go package pkg var Fn = fn
変数、定数と同じ。
構造体
- フィールドが public な場合
// pkg.go package pkg type st struct { Name string }
// export_test.go package pkg type St st
- フィールドも private な場合
// pkg.go package pkg type st struct { name string }
// export_test.go package pkg func NewSt(name string) st { return st{ name: name, } } func (s *st) Name() string { return s.name }
ファクトリ関数を作る。フィールドにアクセスしたければ、Getter も作る。
構造体のメソッド
// pkg.go package pkg type st struct { name string } func (s *st) name() string { return s.name }
// export_test.go package pkg type St struct { st } func (s *st) Name() string { return s.name() }
元の構造体にpublicなメソッドを定義。
publicな構造体に元の構造体を埋め込む。
これでいけます。ここ迷いました~。
インタフェース
// pkg.go package pkg type reader interface { Read() ([]byte, error) }
// export_test.go package pkg type Reader interface { reader }
埋め込む。
おわりに
privateな変数や関数などをテストで扱う方法を書きました。
これらの方法で、無駄に public な定義物を増やすことなくテストが書けそうです。