¿Cómo se imprime en una prueba de Go usando el paquete "testing"?

Resuelto platwp asked hace 10 años • 9 respuestas

Estoy ejecutando una prueba en Go con una declaración para imprimir algo (es decir, para depurar pruebas) pero no imprime nada.

func TestPrintSomething(t *testing.T) {
    fmt.Println("Say hi")
}

Cuando ejecuto go test en este archivo, este es el resultado:

ok      command-line-arguments  0.004s

La única manera de lograr que se imprima, hasta donde yo sé, es imprimirlo mediante t.Error(), así:

func TestPrintSomethingAgain(t *testing.T) {
    t.Error("Say hi")
}

Lo que genera esto:

Say hi
--- FAIL: TestPrintSomethingAgain (0.00 seconds)
    foo_test.go:35: Say hi
FAIL
FAIL    command-line-arguments  0.003s
gom:  exit status 1

Busqué en Google y revisé el manual pero no encontré nada.

platwp avatar Apr 22 '14 03:04 platwp
Aceptado

Las estructuras testing.Ty testing.Bambas tienen un método .Logy .Logfque parece ser lo que estás buscando. .Logy .Logfson similares a fmt.Printy fmt.Printfrespectivamente.

Vea más detalles aquí: http://golang.org/pkg/testing/#pkg-index

fmt.XLas declaraciones de impresión funcionan dentro de las pruebas, pero encontrará que su salida probablemente no esté en la pantalla donde espera encontrarla y, por lo tanto, debería usar los métodos de registro en testing.

Si, como en su caso, desea ver los registros de las pruebas que no fallan, debe proporcionar go testla -vmarca (v para verbosidad). Puede encontrar más detalles sobre las banderas de prueba aquí: https://golang.org/cmd/go/#hdr-Testing_flags

voidlogic avatar Apr 21 '2014 20:04 voidlogic

Por ejemplo,

package verbose

import (
    "fmt"
    "testing"
)

func TestPrintSomething(t *testing.T) {
    fmt.Println("Say hi")
    t.Log("Say bye")
}

go test -v
=== RUN TestPrintSomething
Say hi
--- PASS: TestPrintSomething (0.00 seconds)
    v_test.go:10: Say bye
PASS
ok      so/v    0.002s

comando ir

Descripción de las banderas de prueba.

-v
Verbose output: log all tests as they are run. Also print all
text from Log and Logf calls even if the test succeeds.

Prueba de paquete

función (*T) Registro

func (c *T) Log(args ...interface{})

Log formatea sus argumentos usando el formato predeterminado, análogo a Println, y registra el texto en el registro de errores. Para las pruebas, el texto se imprimirá solo si la prueba falla o si se establece el indicador -test.v. Para los puntos de referencia, el texto siempre se imprime para evitar que el rendimiento dependa del valor del indicador -test.v.

peterSO avatar Apr 21 '2014 20:04 peterSO

t.Log()no aparecerá hasta que se complete la prueba, por lo que si está intentando depurar una prueba que se bloquea o funciona mal, parece que necesita usar fmt.

Sí: así fue hasta Go 1.13 (agosto de 2019) incluido.

Y eso fue seguido en golang.orgel número 24929.

Considere las siguientes (tontas) pruebas automatizadas:

func TestFoo(t *testing.T) {
  t.Parallel()

  for i := 0; i < 15; i++ {
      t.Logf("%d", i)
      time.Sleep(3 * time.Second)
  }
}

func TestBar(t *testing.T) {
  t.Parallel()

  for i := 0; i < 15; i++ {
      t.Logf("%d", i)
      time.Sleep(2 * time.Second)
  }
}

func TestBaz(t *testing.T) {
  t.Parallel()

  for i := 0; i < 15; i++ {
      t.Logf("%d", i)
      time.Sleep(1 * time.Second)
  }
}

Si ejecuto go test -v, no obtengo ningún resultado de registro hasta que todo TestFooesté terminado , luego no obtengo ningún resultado hasta que todo TestBaresté terminado y, nuevamente, no obtengo más resultados hasta que todo TestBazesté terminado.
Esto está bien si las pruebas funcionan, pero si hay algún tipo de error, hay algunos casos en los que almacenar en búfer la salida del registro es problemático:

  • Al iterar localmente, quiero poder hacer un cambio, ejecutar mis pruebas, ver lo que sucede en los registros de inmediato para comprender lo que está sucediendo, presionar CTRL+C para cerrar la prueba antes si es necesario, hacer otro cambio, volver a ejecutar las pruebas, etc.
    Si TestFooes lento (por ejemplo, es una prueba de integración), no obtengo ningún resultado de registro hasta el final de la prueba. Esto ralentiza significativamente la iteración.
  • Si TestFootiene un error que hace que se cuelgue y nunca se complete, no obtendría ningún resultado de registro. En estos casos, t.Logya t.Logfno sirven de nada.
    Esto hace que la depuración sea muy difícil.
  • Además, no solo no obtengo ningún resultado de registro, sino que si la prueba se demora demasiado, el tiempo de espera de la prueba Go finaliza la prueba después de 10 minutos, o si aumento ese tiempo de espera, muchos servidores de CI también finalizarán las pruebas si no hay ningún resultado de registro. registrar la salida después de un cierto período de tiempo (por ejemplo, 10 minutos en CircleCI).
    Ahora mis pruebas han sido canceladas y no tengo nada en los registros que me diga qué sucedió.

Pero para (posiblemente) Go 1.14 (primer trimestre de 2020): CL 127120

prueba: salida del registro de transmisión en modo detallado

La salida ahora es:

=== RUN   TestFoo
=== PAUSE TestFoo
=== RUN   TestBar
=== PAUSE TestBar
=== RUN   TestBaz
=== PAUSE TestBaz
=== CONT  TestFoo
=== CONT  TestBaz
    main_test.go:30: 0
=== CONT  TestFoo
    main_test.go:12: 0
=== CONT  TestBar
    main_test.go:21: 0
=== CONT  TestBaz
    main_test.go:30: 1
    main_test.go:30: 2
=== CONT  TestBar
    main_test.go:21: 1
=== CONT  TestFoo
    main_test.go:12: 1
=== CONT  TestBaz
    main_test.go:30: 3
    main_test.go:30: 4
=== CONT  TestBar
    main_test.go:21: 2
=== CONT  TestBaz
    main_test.go:30: 5
=== CONT  TestFoo
    main_test.go:12: 2
=== CONT  TestBar
    main_test.go:21: 3
=== CONT  TestBaz
    main_test.go:30: 6
    main_test.go:30: 7
=== CONT  TestBar
    main_test.go:21: 4
=== CONT  TestBaz
    main_test.go:30: 8
=== CONT  TestFoo
    main_test.go:12: 3
=== CONT  TestBaz
    main_test.go:30: 9
=== CONT  TestBar
    main_test.go:21: 5
=== CONT  TestBaz
    main_test.go:30: 10
    main_test.go:30: 11
=== CONT  TestFoo
    main_test.go:12: 4
=== CONT  TestBar
    main_test.go:21: 6
=== CONT  TestBaz
    main_test.go:30: 12
    main_test.go:30: 13
=== CONT  TestBar
    main_test.go:21: 7
=== CONT  TestBaz
    main_test.go:30: 14
=== CONT  TestFoo
    main_test.go:12: 5
--- PASS: TestBaz (15.01s)
=== CONT  TestBar
    main_test.go:21: 8
=== CONT  TestFoo
    main_test.go:12: 6
=== CONT  TestBar
    main_test.go:21: 9
    main_test.go:21: 10
=== CONT  TestFoo
    main_test.go:12: 7
=== CONT  TestBar
    main_test.go:21: 11
=== CONT  TestFoo
    main_test.go:12: 8
=== CONT  TestBar
    main_test.go:21: 12
    main_test.go:21: 13
=== CONT  TestFoo
    main_test.go:12: 9
=== CONT  TestBar
    main_test.go:21: 14
=== CONT  TestFoo
    main_test.go:12: 10
--- PASS: TestBar (30.01s)
=== CONT  TestFoo
    main_test.go:12: 11
    main_test.go:12: 12
    main_test.go:12: 13
    main_test.go:12: 14
--- PASS: TestFoo (45.02s)
PASS
ok      command-line-arguments  45.022s

De hecho, está en Go 1.14, como atestigua Dave Cheney en " go test -vsalida de streaming ":

En Go 1.14, go test -vse transmitirá t.Logla salida a medida que ocurra, en lugar de acumularla hasta el final de la ejecución de prueba .

En Go 1.14, las líneas fmt.Printlny están entrelazadas , en lugar de esperar a que se complete la prueba, lo que demuestra que el resultado de la prueba se transmite cuando se utiliza.t.Loggo test -v

Ventaja, según Dave:

Esta es una gran mejora en la calidad de vida de las pruebas de estilo de integración que a menudo se reintentan durante períodos prolongados cuando la prueba falla.
La transmisión t.Logde resultados ayudará a Gophers a depurar esas fallas de prueba sin tener que esperar hasta que se agote el tiempo de espera de toda la prueba para recibir su resultado.

VonC avatar Oct 22 '2019 21:10 VonC

Para probar a veces lo hago

fmt.Fprintln(os.Stdout, "hello")

Además, puede imprimir en:

fmt.Fprintln(os.Stderr, "hello")
Eddy Hernandez avatar Jun 12 '2019 14:06 Eddy Hernandez