メインパッケージに含まれているいくつかの関数をテストしたいのですが、テストではそれらの関数にアクセスできないようです。
サンプルのmain.goファイルは次のようになります。
package main
import (
"log"
)
func main() {
log.Printf(foo())
}
func foo() string {
return "Foo"
}
そして、私のmain_test.goファイルは次のようになります:
package main
import (
"testing"
)
func Foo(t testing.T) {
t.Error(foo())
}
go test main_test.go
を実行すると
# command-line-arguments
.\main_test.go:8: undefined: foo
FAIL command-line-arguments [build failed]
理解できるように、テストファイルを他の場所に移動してmain.goファイルからインポートしようとしても、package main
であるためインポートできませんでした。
そのようなテストを構成する正しい方法は何ですか? main
パッケージからすべてを削除して、すべてを実行し、独自のパッケージ内の関数をテストする単純なメイン関数を追加する必要がありますか、またはテスト中にメインファイルからこれらの関数を呼び出す方法はありますか?
コマンドラインでファイルを指定するときは、それらすべてを指定する必要があります
ここに私の実行があります:
$ ls
main.go main_test.go
$ go test *.go
ok command-line-arguments 0.003s
私のバージョンでは、コマンドラインでmain.goとmain_test.goの両方で実行したことに注意してください
また、_testファイルは正しくありません。テスト関数をTestXXXと呼び、testing.Tへのポインターを取得する必要があります。
変更されたバージョンは次のとおりです。
package main
import (
"testing"
)
func TestFoo(t *testing.T) {
t.Error(foo())
}
変更された出力:
$ go test *.go
--- FAIL: TestFoo (0.00s)
main_test.go:8: Foo
FAIL
FAIL command-line-arguments 0.003s
単体テストはこれまでのところです。ある時点で、実際にプログラムを実行する必要があります。次に、実際のソースからの実際の入力で動作することをテストし、実際の出力を実際の宛先に生成します。実際に。
単体テストを行いたい場合は、main()から移動してください。
これはnot OPの質問に対する直接的な回答であり、main
はほとんどがパッケージ化された関数の呼び出し元であるべきだという以前の回答とコメントに概ね同意しています。そうは言っても、実行可能ファイルのテストに役立つと思われるアプローチを次に示します。 _log.Fataln
_および_exec.Command
_を使用します。
main.go
_を、log.Fatalln()を呼び出す遅延関数で記述して、戻る前にstderrにメッセージを書き込みます。main_test.go
_で、exec.Command(...)
およびcmd.CombinedOutput()
を使用して、予想される結果をテストするために選択した引数でプログラムを実行します。例えば:
_func main() {
// Ensure we exit with an error code and log message
// when needed after deferred cleanups have run.
// Credit: https://medium.com/@matryer/golang-advent-calendar-day-three-fatally-exiting-a-command-line-tool-with-grace-874befeb64a4
var err error
defer func() {
if err != nil {
log.Fatalln(err)
}
}()
// Initialize and do stuff
// check for errors in the usual way
err = somefunc()
if err != nil {
err = fmt.Errorf("somefunc failed : %v", err)
return
}
// do more stuff ...
}
_
_main_test.go
_では、somefunc
が失敗する原因となる不正な引数のテストは次のようになります。
_func TestBadArgs(t *testing.T) {
var err error
cmd := exec.Command(yourprogname, "some", "bad", "args")
out, err := cmd.CombinedOutput()
sout := string(out) // because out is []byte
if err != nil && !strings.Contains(sout, "somefunc failed") {
fmt.Println(sout) // so we can see the full output
t.Errorf("%v", err)
}
}
_
CombinedOutput()
からのerr
は、log.Fatallnのos.Exit(1)
への内部呼び出しからのゼロ以外の終了コードであることに注意してください。そのため、out
を使用してsomefunc
からエラーメッセージを抽出する必要があります。
exec
パッケージは、_cmd.Run
_および_cmd.Output
_も提供します。これらは、一部のテストでは_cmd.CombinedOutput
_よりも適切な場合があります。また、テストの実行前後にセットアップとクリーンアップを行うTestMain(m *testing.M)
関数があると便利です。
_func TestMain(m *testing.M) {
// call flag.Parse() here if TestMain uses flags
os.Mkdir("test", 0777) // set up a temporary dir for generate files
// Create whatever testfiles are needed in test/
// Run all tests and clean up
exitcode := m.Run()
os.RemoveAll("test") // remove the directory and its contents.
os.Exit(exitcode)
_