現在、特定のコードがパニック状態になっているかどうかを確認するテストを作成する方法を検討していますか? Goは recover
を使用してパニックをキャッチすることを知っていますが、たとえばJavaコードとは異なり、スキップするコードを実際に指定することはできませんパニックのケースまたはあなたが何を持っているので、私は機能を持っている場合:
func f(t *testing.T) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
OtherFunctionThatPanics()
t.Errorf("The code did not panic")
}
OtherFunctionThatPanics
がパニックして回復したかどうか、または関数がまったくパニックにならなかったかどうかはわかりません。パニックがない場合にスキップするコードと、パニックがある場合に実行するコードを指定するにはどうすればよいですか?パニックが回復したかどうかを確認するにはどうすればよいですか?
testing
には「成功」という概念はありません。失敗のみです。したがって、上記のコードはほぼ正しいです。このスタイルはもう少しわかりやすいかもしれませんが、基本的には同じことです。
func TestPanic(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Errorf("The code did not panic")
}
}()
// The following is the code under test
OtherFunctionThatPanics()
}
私は通常、testing
がかなり弱いと感じています。 Ginkgo のような、より強力なテストエンジンに興味があるかもしれません。完全なGinkgoシステムが必要ない場合でも、testing
とともに使用できるマッチャーライブラリ Gomega のみを使用できます。 Gomegaには、次のようなマッチャーが含まれています。
Expect(OtherFunctionThatPanics).To(Panic())
パニックチェックを簡単な関数にまとめることもできます:
func TestPanic(t *testing.T) {
assertPanic(t, OtherFunctionThatPanics)
}
func assertPanic(t *testing.T, f func()) {
defer func() {
if r := recover(); r == nil {
t.Errorf("The code did not panic")
}
}()
f()
}
testify/assert を使用すると、1行になります。
_func TestOtherFunctionThatPanics(t *testing.T) {
assert.Panics(t, OtherFunctionThatPanics, "The code did not panic")
}
_
または、OtherFunctionThatPanics
にfunc()
以外の署名がある場合:
_func TestOtherFunctionThatPanics(t *testing.T) {
assert.Panics(t, func() { OtherFunctionThatPanics(arg) }, "The code did not panic")
}
_
まだ証言していない場合は、 testify/mock も確認してください。超シンプルなアサーションとモック。
複数のテストケースをループする場合、次のようなものを探します。
package main
import (
"reflect"
"testing"
)
func TestYourFunc(t *testing.T) {
type args struct {
arg1 int
arg2 int
arg3 int
}
tests := []struct {
name string
args args
want []int
wantErr bool
wantPanic bool
}{
//TODO: write test cases
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer func() {
r := recover()
if (r != nil) != tt.wantPanic {
t.Errorf("SequenceInt() recover = %v, wantPanic = %v", r, tt.wantPanic)
}
}()
got, err := YourFunc(tt.args.arg1, tt.args.arg2, tt.args.arg3)
if (err != nil) != tt.wantErr {
t.Errorf("YourFunc() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("YourFunc() = %v, want %v", got, tt.want)
}
})
}
}
パニックの内容を確認する必要がある場合、回復した値を型キャストできます。
func TestIsAheadComparedToPanicsWithDifferingStreams(t *testing.T) {
defer func() {
err := recover().(error)
if err.Error() != "Cursor: cannot compare cursors from different streams" {
t.Fatalf("Wrong panic message: %s", err.Error())
}
}()
c1 := CursorFromserializedMust("/foo:0:0")
c2 := CursorFromserializedMust("/bar:0:0")
// must panic
c1.IsAheadComparedTo(c2)
}
テストしているコードがパニックしない場合ORエラーでパニックOR期待するエラーメッセージでパニックすると、テストは失敗しますあなたが望むものです)。
パニックを入力することで、どの機能がパニックしたかをテストできます
package main
import "fmt"
func explode() {
// Cause a panic.
panic("WRONG")
}
func explode1() {
// Cause a panic.
panic("WRONG1")
}
func main() {
// Handle errors in defer func with recover.
defer func() {
if r := recover(); r != nil {
var ok bool
err, ok := r.(error)
if !ok {
err = fmt.Errorf("pkg: %v", r)
fmt.Println(err)
}
}
}()
// These causes an error. change between these
explode()
//explode1()
fmt.Println("Everything fine")
}