go build した結果のバイナリを実行している場合と go test している場合とで、挙動を変えるための方法です。
後々追記するかもしれませんが、現時点では2つの方法があります。(適用範囲が異なります)
それぞれの方法について、特徴と使いどころを考えたいと思います。
- flag を使う方法
- build tags を使う方法
flagを使う方法
制限が少なく、かつ手間がかからない方法です。
方法
元ネタは、以下の stackoverflow の質問・回答です。
How do I know I'm running within “go test”
flag.Lookup("test.v") != nil
説明
go test した場合、"test.XXX" というフラグが多数定義されますが、そのうちの一つのフラグが定義されているかどうかで判別しています。
このとき、実際にコマンドラインで指定しなくても判別が可能です。
上記のコード片の様に至極手軽に実装できますが、一応パッケージにしてみました。
bitbucket.org/shu/testa
testa.IsTesting() bool
特徴
init() を含めて、どこでも使うことができます。
flag.Parse() していなくても判別可能です。
build tags を使う方法と比べても、制限がありません。
テストコードだけではなく、テスト対象のコード内でも使うことができます。
使いどころ
テスト時に特殊な挙動を追加で行うことが期待されているパッケージの内部で使えるかもしれません(?)
一般的な話になりますが、非テストコード(特にテスト対象コード)でテスト時・非テスト時の判断を行うということは、そのようなパッケージでは非テスト時の挙動がテストできない、ということになります。
外部の要因で挙動を変えられるようにしたい場合は、パッケージの構造として、フラグ変数や関数オブジェクト、もしくはインターフェイスを媒介した挙動変更の情報を受け取れるようにした方が良いでしょう。
ただ、例えば「テスト時にはログに追加情報を出す」といった利用であれば、殆ど悪影響は無いと思います。
本筋の処理とは別の処理(具体的に言うと、テスト対象外の処理)を変更する条件として使うのであれば、まあ、問題にはならないと思います。
build tags を使う方法
テストコード内で、go test か判別する方法です。
XXX_test.go ファイル内で、利用しているパッケージのオプションやらをテスト向けに変更する方法です。
方法
func init() {
somepkg.SetOption("testing")
}
特徴
flag を使う方法とは異なり、他のパッケージに依存しません。
使えるのは、テストコード内のみです。
そのため、「テスト時ではない場合」ということを判別する方法にはなりません。
(そのような判別を行うのは推奨しませんけどね)
上記の判別が必要な場合、テスト時ではない場合は初期値を、テスト時は上記の方法でその初期値を上書きするように、パッケージを設計します。
使いどころ
テスト時にのみパッケージのグローバルなオプションもしくは変数を変更する場合に使えます。