Como você imprime em um teste Go usando o pacote de “teste”?

129

Estou executando um teste em Go com uma instrução para imprimir algo (ou seja, para depuração de testes), mas não está imprimindo nada.

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

Quando eu executo go test neste arquivo, esta é a saída:

ok      command-line-arguments  0.004s

A única maneira de realmente imprimir, pelo que eu sei, é imprimi-lo via t.Error (), assim:

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

O que resulta em:

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

Pesquisei no Google e olhei o manual, mas não encontrei nada.

platwp
fonte
Isso poderia ser possível para o Go 1.14 (primeiro trimestre de 2010). Veja minha resposta abaixo .
VonC
@VonC s / b Q1 2020
user2133814
@ user2133814 Concordo, deveria ser 2020 de fato, não 2010. A resposta abaixo menciona 2020. Eu editei essa resposta, com uma referência ao artigo de Dave Cheney sobre esse novo recurso.
VonC

Respostas:

142

Os structs testing.Te testing.Bambos têm um método .Loge .Logfque parece ser o que você está procurando. .Loge .Logfsão semelhantes a fmt.Printefmt.Printf respectivamente.

Veja mais detalhes aqui: http://golang.org/pkg/testing/#pkg-index

fmt.Ximprimir declarações fazer testes no interior de trabalho, mas você vai encontrar a sua saída não é, provavelmente, na tela onde você espera encontrá-lo e, portanto, por que você deve usar os métodos de registro emtesting .

Se, como no seu caso, você quiser ver os logs dos testes que não estão falhando, você deve fornecer go testo -vsinalizador (v para detalhamento). Mais detalhes sobre sinalizadores de teste podem ser encontrados aqui: https://golang.org/cmd/go/#hdr-Testing_flags

voidlogic
fonte
15
t.Log () não aparecerá até que o teste seja concluído, portanto, se você estiver tentando depurar um teste que está travando ou com desempenho ruim, parece que você precisa usar o fmt. Veja a resposta de PeterSO para usar go test -v para mostrar a saída de fmt.Println ao executar testes.
voutassauro,
142

Por exemplo,

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 vai

Descrição dos sinalizadores de teste

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

Teste de pacote

função (* T) Log

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

O log formata seus argumentos usando a formatação padrão, análoga a Println, e registra o texto no log de erros. Para testes, o texto será impresso apenas se o teste falhar ou se o sinalizador -test.v estiver definido. Para benchmarks, o texto é sempre impresso para evitar que o desempenho dependa do valor do sinalizador -test.v.

PeterSO
fonte
21
verboseé o que eu estava procurando.
cevaris
2
anwa para ver a saída do log no moethod ou está testando a si mesmo
filthy_wizard
7

t.Log()não aparecerá até que o teste seja concluído, portanto, se você estiver tentando depurar um teste que está travando ou com desempenho ruim, parece que você precisa usar fmt.

Sim: era esse o caso até Go 1.13 (agosto de 2019) incluído.

E isso foi seguido na golang.orgedição 24929

Considere os seguintes testes automatizados (bobos):

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

Se eu executar go test -v, não recebo nenhuma saída de log até que tudo TestFooseja feito , nenhuma saída até que tudo TestBarseja feito e, novamente, nenhuma saída até que tudo TestBazseja feito.
Isso é bom se os testes estiverem funcionando, mas se houver algum tipo de bug, há alguns casos em que o armazenamento em buffer da saída do log é problemático:

  • Ao iterar localmente, quero ser capaz de fazer uma alteração, executar meus testes, ver o que está acontecendo nos logs imediatamente para entender o que está acontecendo, pressione CTRL + C para encerrar o teste mais cedo se necessário, faça outra alteração, execute os testes e assim por diante.
    E seTestFoo for lento (por exemplo, é um teste de integração), não recebo nenhuma saída de log até o final do teste. Isso diminui significativamente a iteração.
  • Se TestFoohouver um bug que faz com que ele trave e nunca seja concluído, eu não obteria nenhuma saída de log. Nestes casos, t.Loge t.Logfsão inúteis.
    Isso torna a depuração muito difícil.
  • Além disso, não apenas recebo nenhuma saída de log, mas se o teste travar por muito tempo, o tempo limite do teste Go elimina o teste após 10 minutos, ou se eu aumentar esse tempo limite, muitos servidores de CI também encerrarão os testes se não houver log de saída após um determinado período de tempo (por exemplo, 10 minutos em CircleCI).
    Portanto, agora meus testes foram interrompidos e não tenho nada nos registros que me diga o que aconteceu.

Mas para (possivelmente) Go 1.14 (Q1 2020): CL 127120

teste: fluxo de saída de registro em modo detalhado

A saída agora é:

=== 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

Na verdade, está no Go 1.14, como Dave Cheney atesta em " go test -vfluxo de saída ":

No Go 1.14, go test -vo fluxo de t.Logsaída será transmitido à medida que acontecer, em vez de armazená-lo até o final do teste .

No Go 1.14, as linhas fmt.Printlne t.Logsão intercaladas , em vez de aguardar a conclusão do teste, demonstrando que a saída do teste é transmitida quando go test -vé usada.

Vantagem, de acordo com Dave:

Esta é uma grande melhoria de qualidade de vida para testes de estilo de integração que geralmente são repetidos por longos períodos quando o teste está falhando.
A t.Logsaída de streaming ajudará os Gophers a depurar essas falhas de teste sem ter que esperar até que todo o teste expire para receber sua saída.

VonC
fonte
5

Para testar às vezes eu faço

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

Além disso, você pode imprimir em:

fmt.Fprintln(os.Stderr, "hello)
Eddy Hernandez
fonte
O primeiro só pode ser fmt.Println("hello").
Duncan Jones,
2

t.Loge t.Logfimprima em seu teste, mas muitas vezes pode ser perdido, pois imprime na mesma linha do seu teste. O que eu faço é registrá-los de uma forma que os destaque, ou seja,

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 o imprime no 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
fonte
-2

O *_test.goarquivo é uma fonte Go como os outros, você pode inicializar um novo logger toda vez se precisar despejar estruturas de dados complexas, aqui um exemplo:

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

Então, todas as vezes, em todos os testes:

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
fonte