Go内でいくつかの異なるテストパッケージの命名戦略を見てきましたが、それぞれの長所と短所、使用すべきものを知りたいと思いました。
戦略1:
ファイル名:github.com/user/myfunc.go
package myfunc
テストファイル名:github.com/user/myfunc_test.go
package myfunc
例については、 bzip2 を参照してください。
戦略2:
ファイル名:github.com/user/myfunc.go
package myfunc
テストファイル名:github.com/user/myfunc_test.go
package myfunc_test
import (
"github.com/user/myfunc"
)
例については、 wire を参照してください。
戦略3:
ファイル名:github.com/user/myfunc.go
package myfunc
テストファイル名:github.com/user/myfunc_test.go
package myfunc_test
import (
. "myfunc"
)
例については、 strings を参照してください。
Go標準ライブラリは、戦略1と戦略2を組み合わせて使用しているようです。パッケージプライベートメソッドをテストできないことを意味するので、テストパッケージにpackage *_test
を追加するのは苦痛ですが、気付いていない隠れた利点があるかもしれません。
リストした3つの戦略の基本的な違いは、テストコードがテスト対象のコードと同じパッケージにあるかどうかです。テストファイルでpackage myfunc
またはpackage myfunc_test
を使用するかどうかは、テストを実行するかどうかによって異なります white-box または black-box 。
プロジェクトで両方の方法を使用しても問題はありません。たとえば、myfunc_whitebox_test.go
とmyfunx_blackbox_test.go
を使用できます。
package myfunc_test
を使用します。これにより、 エクスポートされた識別子 のみを使用していることが保証されます。package myfunc
を使用して、エクスポートされていない識別子にアクセスできるようにします。エクスポートされていない変数、関数、およびメソッドへのアクセスを必要とする単体テストに適しています。myfunc_test.go
はpackage myfunc
を使用します—この場合、myfunc_test.go
のテストコードはmyfunc.go
でテストされているコードと同じパッケージ。この例ではmyfunc
です。myfunc_test.go
はpackage myfunc_test
を使用します—この場合、myfunc_test.go
のテストコードは別のパッケージとしてコンパイルし、メインのテストバイナリとリンクして実行します。」 [ソース: test.go ソースコードの58〜59行目]myfunc_test.go
はpackage myfunc_test
を使用しますが、ドット表記を使用してmyfunc
をインポートします—これはストラテジー2の変形ですが、ドット表記を使用してmyfunc
をインポートします。可能な限り戦略1を使用する必要があります。特別なfoo_test
パッケージ名を使用してインポートサイクルを回避することができますが、ほとんどの場合、同じメカニズムで標準ライブラリをテストできます。たとえば、strings
パッケージはtesting
に依存するため、strings
は戦略1でテストできません。先ほど言ったように、戦略2または3では、パッケージのプライベート識別子にアクセスできないため、通常は必要がない限り使用しない方が良いでしょう。
テストの範囲に依存します。エクスポートされたAPIを介してパッケージを使用していることを確認するために、高レベルのテスト(統合、受け入れなど)はおそらく別のパッケージに配置する必要があります。
テスト対象にする必要のある内部構造が多数ある大きなパッケージがある場合は、テストに同じパッケージを使用します。しかし、それはあなたのテストが私的な状態のビットにアクセスするための招待状ではありません。それはリファクタリングを悪夢にするでしょう。 goで構造体を書くとき 私はしばしばインターフェースを実装しています。テストから呼び出すのはこれらのインターフェイスメソッドであり、すべてのヘルパーメソッド/関数を個別に呼び出すわけではありません。