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

129

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 ir a probar en este archivo, este es el resultado:

ok      command-line-arguments  0.004s

La única forma de hacer que se imprima realmente, hasta donde yo sé, es imprimirlo a través de t.Error (), así:

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

Que produce 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
fuente
Esto podría ser posible para Go 1.14 (primer trimestre de 2010). Vea mi respuesta a continuación .
VonC
@VonC s / b Q1 2020
user2133814
@ user2133814 De acuerdo, debería ser 2020 de hecho, no 2010. La respuesta a continuación sí menciona 2020. He editado dicha respuesta, con una referencia al artículo de Dave Cheney sobre esa nueva característica.
VonC

Respuestas:

142

Las estructuras testing.Ty testing.Bambos tienen un método .Logy .Logfque suena a ser lo que estás buscando. .Logy .Logfson similares a fmt.Printyfmt.Printf respectivamente.

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

fmt.XDeclaraciones de impresión hacen pruebas en el interior de trabajo, pero se puede encontrar su salida no es, probablemente, en la pantalla donde se espera encontrar y, por lo tanto, por qué debería utilizar los métodos de registro entesting .

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
fuente
15
t.Log () no aparecerá hasta que se complete la prueba, por lo que si está tratando de depurar una prueba que se cuelga o funciona mal, parece que necesita usar fmt. Vea la respuesta de PeterSO para usar go test -v para mostrar la salida de fmt.Println al ejecutar pruebas.
voutasaurus
142

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

func (* 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 la marca -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
fuente
21
verbosees lo que estaba buscando.
Cevaris
2
anwa para ver la salida del registro en el método que está probando a sí mismo
filthy_wizard
7

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

Sí: ese fue el caso hasta Go 1.13 (agosto de 2019) incluido.

Y eso fue seguido en el golang.orgnú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 ninguna salida de registro hasta que todo TestFooesté hecho , luego ninguna salida hasta que todo TestBaresté hecho, y nuevamente no más salida hasta que todo TestBazesté hecho.
Esto está bien si las pruebas están funcionando, pero si hay algún tipo de error, hay algunos casos en los que la salida del registro en búfer es problemática:

  • Al iterar localmente, quiero poder hacer un cambio, ejecutar mis pruebas, ver lo que está sucediendo en los registros de inmediato para comprender qué está sucediendo, presionar CTRL + C para cerrar la prueba antes si es necesario, hacer otro cambio, volver a ejecutar las pruebas y así sucesivamente.
    SiTestFoo es 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 para 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 cuelga demasiado tiempo, el tiempo de espera de la prueba de Go mata la prueba después de 10 minutos, o si aumento ese tiempo de espera, muchos servidores de CI también eliminarán las pruebas si no hay registro de salida después de una cierta cantidad de tiempo (por ejemplo, 10 minutos en CircleCI).
    Así que ahora mis pruebas están eliminadas y no tengo nada en los registros que me diga qué pasó.

Pero para (posiblemente) Go 1.14 (Q1 2020): CL 127120

prueba: salida de registro de flujo en modo detallado

La salida ahora es:

=== RUN   TestFoo
=== PAUSE TestFoo
=== RUN   TestBar
=== PAUSE TestBar
=== RUN   TestGaz
=== PAUSE TestGaz
=== CONT  TestFoo
    TestFoo: main_test.go:14: hello from foo
=== CONT  TestGaz
=== CONT  TestBar
    TestGaz: main_test.go:38: hello from gaz
    TestBar: main_test.go:26: hello from bar
    TestFoo: main_test.go:14: hello from foo
    TestBar: main_test.go:26: hello from bar
    TestGaz: main_test.go:38: hello from gaz
    TestFoo: main_test.go:14: hello from foo
    TestGaz: main_test.go:38: hello from gaz
    TestBar: main_test.go:26: hello from bar
    TestFoo: main_test.go:14: hello from foo
    TestGaz: main_test.go:38: hello from gaz
    TestBar: main_test.go:26: hello from bar
    TestGaz: main_test.go:38: hello from gaz
    TestFoo: main_test.go:14: hello from foo
    TestBar: main_test.go:26: hello from bar
--- PASS: TestFoo (1.00s)
--- PASS: TestGaz (1.00s)
--- PASS: TestBar (1.00s)
PASS
ok      dummy/streaming-test    1.022s

De hecho, está en Go 1.14, como lo atestigua Dave Cheney en " go test -vsalida de transmisión ":

En Go 1.14, go test -vtransmitirá la t.Logsalida a medida que ocurre, en lugar de acumularla hasta el final de la ejecución de prueba .

En Go 1.14, las líneas fmt.Printlny t.Logse intercalan , en lugar de esperar a que se complete la prueba, lo que demuestra que la salida de la prueba se transmite cuando go test -vse usa.

Ventaja, según Dave:

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

VonC
fuente
5

Para probar a veces lo hago

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

Además, puede imprimir en:

fmt.Fprintln(os.Stderr, "hello)
Eddy Hernández
fuente
El primero de ellos puede ser simplemente fmt.Println("hello").
Duncan Jones
2

t.Loge t.Logfimprime en su prueba, pero a menudo se puede perder ya que se imprime en la misma línea que su prueba. Lo que hago es registrarlos de manera que se destaquen, es decir

t.Run("FindIntercomUserAndReturnID should find an intercom user", func(t *testing.T) {

    id, err := ic.FindIntercomUserAndReturnID("[email protected]")
    assert.Nil(t, err)
    assert.NotNil(t, id)

    t.Logf("\n\nid: %v\n\n", *id)
})

que lo imprime en la terminal como,

=== RUN   TestIntercom
=== RUN   TestIntercom/FindIntercomUserAndReturnID_should_find_an_intercom_user
    TestIntercom/FindIntercomUserAndReturnID_should_find_an_intercom_user: intercom_test.go:34:

        id: 5ea8caed05a4862c0d712008

--- PASS: TestIntercom (1.45s)
    --- PASS: TestIntercom/FindIntercomUserAndReturnID_should_find_an_intercom_user (1.45s)
PASS
ok      github.com/RuNpiXelruN/third-party-delete-service   1.470s
RuNpiXelruN
fuente
-2

El *_test.goarchivo es una fuente Go como los demás, puede inicializar un nuevo registrador cada vez que necesite volcar una estructura de datos compleja, aquí un ejemplo:

// initZapLog is delegated to initialize a new 'log manager'
func initZapLog() *zap.Logger {
    config := zap.NewDevelopmentConfig()
    config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
    config.EncoderConfig.TimeKey = "timestamp"
    config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
    logger, _ := config.Build()
    return logger
}

Entonces, cada vez, en cada prueba:

func TestCreateDB(t *testing.T) {
    loggerMgr := initZapLog()
    // Make logger avaible everywhere
    zap.ReplaceGlobals(loggerMgr)
    defer loggerMgr.Sync() // flushes buffer, if any
    logger := loggerMgr.Sugar()
    logger.Debug("START")
    conf := initConf()
    /* Your test here
    if false {
        t.Fail()
    }*/
}
alessiosavi
fuente