test serp seomofo google checker check testing go

testing - serp - ¿Cómo probar el pánico?



test seo tags (5)

Actualmente estoy reflexionando sobre cómo escribir pruebas que verifiquen si una determinada pieza de código entró en pánico. Sé que Go usa la recover para atrapar los pánicos, pero a diferencia de, por ejemplo, el código Java, no se puede especificar qué código se debe omitir en caso de pánico o qué tiene. Entonces, si tengo una función:

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") }

Realmente no puedo decir si OtherFunctionThatPanics entró en pánico y nos recuperamos, o si la función no entró en pánico en absoluto. ¿Cómo especifico qué código omitir si no hay pánico y qué código ejecutar si hay pánico? ¿Cómo puedo verificar si hubo algo de pánico del que nos recuperamos?


Al recorrer múltiples casos de prueba, iría por algo como esto:

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) }

Ir al patio de recreo


Cuando necesite verificar el contenido del pánico, puede escribir el valor recuperado:

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) } }) } }

Si el código que está probando no entra en pánico O entra en pánico con un error O entra en pánico con el mensaje de error que espera, la prueba fallará (que es lo que desea).


Puede probar qué función en pánico dando una entrada al pánico

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") }

http://play.golang.org/p/ORWBqmPSVA


Si usa testify/assert , entonces es una línea:

func TestOtherFunctionThatPanics(t *testing.T) { assert.Panics(t, OtherFunctionThatPanics, "The code did not panic") }

O, si su OtherFunctionThatPanics tiene una firma distinta de func() :

func TestOtherFunctionThatPanics(t *testing.T) { assert.Panics(t, func() { OtherFunctionThatPanics(arg) }, "The code did not panic") }

Si aún no has probado testificar, también echa un vistazo a testify/mock . Súper simples afirmaciones y simulacros.


testing realmente no tienen el concepto de "éxito", solo fracaso. Entonces su código anterior es correcto. Puede encontrar este estilo un poco más claro, pero es básicamente lo mismo.

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() }

En general, las testing son bastante débiles. Puede que le interesen motores de prueba más potentes como Ginkgo . Incluso si no desea el sistema Ginkgo completo, puede usar solo su biblioteca de Gomega , Gomega , que puede usarse junto con las testing . Gomega incluye matchers como:

Expect(OtherFunctionThatPanics).To(Panic())

También puede resumir la comprobación de pánico en una función simple:

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() }