この質問: Go で os.exit シナリオをテストする方法(およびその中で最も投票された回答) は、os.Exit()
go 内でシナリオをテストする方法を設定します。os.Exit()
簡単に傍受できないため、バイナリを再度呼び出して終了値を確認する方法が使用されます。この方法については、Andrew Gerrand (Go チームのコア メンバーの 1 人) によるこのプレゼンテーションのスライド 23 で説明されています。コードは非常に単純で、以下に完全に再現されています。
関連するテスト ファイルとメイン ファイルは次のようになります(このファイルのペアだけが MVCE であることに注意してください)。
package foo
import (
"os"
"os/exec"
"testing"
)
func TestCrasher(t *testing.T) {
if os.Getenv("BE_CRASHER") == "1" {
Crasher() // This causes os.Exit(1) to be called
return
}
cmd := exec.Command(os.Args[0], "-test.run=TestCrasher")
cmd.Env = append(os.Environ(), "BE_CRASHER=1")
err := cmd.Run()
if e, ok := err.(*exec.ExitError); ok && !e.Success() {
fmt.Printf("Error is %v\n", e)
return
}
t.Fatalf("process ran with err %v, want exit status 1", err)
}
と
package foo
import (
"fmt"
"os"
)
// Coverage testing thinks (incorrectly) that the func below is
// never being called
func Crasher() {
fmt.Println("Going down in flames!")
os.Exit(1)
}
ただし、この方法には特定の制限があるようです。
goveralls / coveralls.io を使用したカバレッジ テストは機能しません。たとえば、こちらの例(上記と同じコードですが、便宜上 github に配置されています) を参照してください。ここではカバレッジ テストが生成されます。つまり、実行中のテスト関数は記録されません。質問に答えるためにこれらのリンクは必要ないことに注意してください-上記の例はうまく機能します-上記をgithubに入れ、travisを介してcoveralls.ioにたどり着いた場合に何が起こるかを示すためだけです.
テスト バイナリを再実行すると、壊れやすいように見えます。
具体的には、リクエストに応じて、カバレッジの失敗のスクリーンショット (リンクではなく) を以下に示します。赤い陰影は、coveralls.io に関する限り、Crasher()
呼び出されていないことを示します。
これを回避する方法はありますか?特に1点目。
golang レベルでの問題は次のとおりです。
Goveralls フレームワークが実行
go test -cover ...
され、上記のテストが呼び出されます。上記のテストは、OS 引数
exec.Command / .Run
なしで呼び出します-cover
etc. を無条件に
-cover
引数リストに入れるのは魅力的ではありません。これは、非カバレッジ テスト内で (サブプロセスとして) カバレッジ テストを実行することになり、引数リストを解析して-cover
etc. の存在を確認することは、非常に重要な解決策のように思えます。etc. を引数リストに入れても
-cover
、同じファイルに 2 つのカバレッジ出力が書き込まれ、うまくいきません。何らかの方法でマージする必要があります。私がそれに最も近いのは、この golang issueです。
概要
私が求めているのは、go カバレッジ テストを (できれば travis、goveralls、および coveralls.io を介して) 実行する簡単な方法であり、テストされたルーチンが で終了するテスト ケースと、OS.exit()
そのテストのカバレッジが記録されているテスト ケースの両方が可能です。 . 上記の re-exec メソッドを使用することを強く希望します (それが機能する場合)。
ソリューションは、 のカバレッジ テストを表示する必要がありCrasher()
ます。カバレッジテストから除外Crasher()
することはオプションではありません.現実の世界では、私がやろうとしていることは、より複雑な関数をテストすることlog.Fatalf()
です。私がカバレッジ テストを行っているのは、それらの条件のテストが適切に機能することです。