web-dev-qa-db-ja.com

Go言語でテストするための適切なパッケージの命名

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を追加するのは苦痛ですが、気付いていない隠れた利点があるかもしれません。

76
Dan

リストした3つの戦略の基本的な違いは、テストコードがテスト対象のコードと同じパッケージにあるかどうかです。テストファイルでpackage myfuncまたはpackage myfunc_testを使用するかどうかは、テストを実行するかどうかによって異なります white-box または black-box

プロジェクトで両方の方法を使用しても問題はありません。たとえば、myfunc_whitebox_test.gomyfunx_blackbox_test.goを使用できます。

テストコードパッケージの比較

  • ブラックボックステスト:package myfunc_testを使用します。これにより、 エクスポートされた識別子 のみを使用していることが保証されます。
  • ホワイトボックステスト:package myfuncを使用して、エクスポートされていない識別子にアクセスできるようにします。エクスポートされていない変数、関数、およびメソッドへのアクセスを必要とする単体テストに適しています。

質問にリストされている戦略の比較

  • 戦略1:ファイルmyfunc_test.gopackage myfuncを使用します—この場合、myfunc_test.goのテストコードはmyfunc.goでテストされているコードと同じパッケージ。この例ではmyfuncです。
  • 戦略2:ファイルmyfunc_test.gopackage myfunc_testを使用します—この場合、myfunc_test.goのテストコードは別のパッケージとしてコンパイルし、メインのテストバイナリとリンクして実行します。」 [ソース: test.go ソースコードの58〜59行目]
  • 戦略3:ファイルmyfunc_test.gopackage myfunc_testを使用しますが、ドット表記を使用してmyfuncをインポートします—これはストラテジー2の変形ですが、ドット表記を使用してmyfuncをインポートします。
95
Matthew Rankin

可能な限り戦略1を使用する必要があります。特別なfoo_testパッケージ名を使用してインポートサイクルを回避することができますが、ほとんどの場合、同じメカニズムで標準ライブラリをテストできます。たとえば、stringsパッケージはtestingに依存するため、stringsは戦略1でテストできません。先ほど言ったように、戦略2または3では、パッケージのプライベート識別子にアクセスできないため、通常は必要がない限り使用しない方が良いでしょう。

17
guelfey

テストの範囲に依存します。エクスポートされたAPIを介してパッケージを使用していることを確認するために、高レベルのテスト(統合、受け入れなど)はおそらく別のパッケージに配置する必要があります。

テスト対象にする必要のある内部構造が多数ある大きなパッケージがある場合は、テストに同じパッケージを使用します。しかし、それはあなたのテストが私的な状態のビットにアクセスするための招待状ではありません。それはリファクタリングを悪夢にするでしょう。 goで構造体を書くとき 私はしばしばインターフェースを実装しています。テストから呼び出すのはこれらのインターフェイスメソッドであり、すべてのヘルパーメソッド/関数を個別に呼び出すわけではありません。

17
mdwhatcott