Bagaimana Anda mencetak dalam pengujian Go menggunakan paket "pengujian"?


129

Saya menjalankan tes di Go dengan pernyataan untuk mencetak sesuatu (yaitu untuk debugging tes) tetapi tidak mencetak apa pun.

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

Ketika saya menjalankan go test pada file ini, ini adalah outputnya:

ok      command-line-arguments  0.004s

Satu-satunya cara untuk benar-benar mencetaknya, sejauh yang saya tahu, adalah dengan mencetaknya melalui t.Error (), seperti:

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

Yang menghasilkan ini:

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

Saya telah mencari di Google dan melihat-lihat manual tetapi tidak menemukan apa pun.


Ini dapat dilakukan untuk Go 1.14 (Q1 2010). Lihat jawaban saya di bawah .
VonC

@VonC s / b Q1 2020
pengguna2133814

@ user2133814 Setuju, seharusnya memang tahun 2020, bukan 2010. Jawaban di bawah memang menyebutkan tahun 2020. Saya telah mengedit jawaban tersebut, dengan mengacu pada artikel Dave Cheney tentang fitur baru tersebut.
VonC

Jawaban:


142

Structs testing.Tdan testing.Bkeduanya memiliki metode .Logdan .Logfyang terdengar seperti yang Anda cari. .Logdan .Logfmirip dengan fmt.Printdan fmt.Printfmasing - masing.

Lihat detail selengkapnya di sini: http://golang.org/pkg/testing/#pkg-index

fmt.Xpernyataan cetak lakukan pekerjaan di dalam tes, tetapi Anda akan menemukan output mereka mungkin tidak pada layar di mana Anda berharap untuk menemukan itu dan, karenanya, mengapa Anda harus menggunakan metode logging di testing.

Jika, seperti dalam kasus Anda, Anda ingin melihat log untuk tes yang tidak gagal, Anda harus menyediakan go testsatu -vbendera (v untuk bertele-tele). Detail selengkapnya tentang flag pengujian dapat ditemukan di sini: https://golang.org/cmd/go/#hdr-Testing_flags


15
t.Log () tidak akan muncul hingga pengujian selesai, jadi jika Anda mencoba men-debug pengujian yang macet atau berkinerja buruk, tampaknya Anda perlu menggunakan fmt. Lihat jawaban PeterSO untuk menggunakan go test -v untuk menampilkan keluaran fmt.Println saat menjalankan pengujian.
voutasaurus

142

Sebagai contoh,

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

Perintah pergi

Deskripsi pengujian bendera

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

Pengujian paket

func (* T) Log

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

Log memformat argumennya menggunakan pemformatan default, mirip dengan Println, dan mencatat teks di log kesalahan. Untuk pengujian, teks akan dicetak hanya jika pengujian gagal atau tanda -test.v disetel. Untuk tolok ukur, teks selalu dicetak untuk menghindari kinerja yang bergantung pada nilai tanda -test.v.


21
verboseadalah apa yang saya cari.
cevaris

2
anwa untuk melihat keluaran log di metode yang Anda uji sendiri
filthy_wizard

7

t.Log()tidak akan muncul hingga pengujian selesai, jadi jika Anda mencoba men-debug pengujian yang macet atau berkinerja buruk, tampaknya Anda perlu menggunakan fmt.

Ya: itulah yang terjadi hingga Go 1.13 (Agustus 2019) disertakan.

Dan itu diikuti dalam golang.orgedisi 24929

Pertimbangkan tes otomatis (konyol) berikut:

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

Jika saya menjalankan go test -v, saya tidak mendapatkan output log sampai semua TestFooselesai , kemudian tidak ada output sampai semua TestBarselesai, dan sekali lagi tidak ada output lagi sampai semua TestBazselesai.
Ini baik-baik saja jika pengujian berfungsi, tetapi jika ada semacam bug, ada beberapa kasus di mana keluaran log buffering bermasalah:

  • Saat melakukan iterasi secara lokal, saya ingin dapat membuat perubahan, menjalankan pengujian saya, melihat apa yang terjadi di log segera untuk memahami apa yang terjadi, tekan CTRL + C untuk menutup pengujian lebih awal jika perlu, buat perubahan lain, ulangi menjalankan tes, dan seterusnya.
    Jika TestFoolambat (misalnya, ini adalah uji integrasi), saya tidak mendapatkan keluaran log hingga pengujian paling akhir. Ini secara signifikan memperlambat iterasi.
  • Jika TestFoomemiliki bug yang menyebabkannya hang dan tidak pernah selesai, saya tidak akan mendapatkan keluaran log apa pun. Dalam kasus ini, t.Logdan t.Logftidak ada gunanya sama sekali.
    Ini membuat proses debug menjadi sangat sulit.
  • Selain itu, saya tidak hanya mendapatkan keluaran log, tetapi jika pengujian berhenti terlalu lama, baik batas waktu pengujian Go akan menghentikan pengujian setelah 10 menit, atau jika saya meningkatkan batas waktu tersebut, banyak server CI juga akan menghentikan pengujian jika tidak ada log output setelah jangka waktu tertentu (misalnya, 10 menit di CircleCI).
    Jadi sekarang tes saya dihentikan dan saya tidak memiliki apa pun di log untuk memberi tahu saya apa yang terjadi.

Tetapi untuk (mungkin) Go 1.14 (Q1 2020): CL 127120

pengujian: keluaran log streaming dalam mode verbose

Outputnya sekarang adalah:

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

Ini memang ada di Go 1.14, seperti yang dibuktikan oleh Dave Cheney dalam " go test -voutput streaming ":

Di Go 1.14, go test -vakan mengalirkan t.Logkeluaran saat terjadi, daripada menimbunnya hingga akhir uji coba .

Di bawah Go 1.14, garis fmt.Printlndan disisipkan , daripada menunggu pengujian selesai, mendemonstrasikan bahwa keluaran pengujian dialirkan saat digunakan.t.Loggo test -v

Keuntungan, menurut Dave:

Ini adalah peningkatan kualitas hidup yang bagus untuk pengujian gaya integrasi yang sering kali mencoba ulang untuk waktu yang lama saat pengujian gagal. Output
streaming t.Logakan membantu Gophers men-debug kegagalan tes tersebut tanpa harus menunggu hingga waktu tes habis untuk menerima outputnya.


5

Untuk pengujian terkadang saya lakukan

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

Anda juga dapat mencetak ke:

fmt.Fprintln(os.Stderr, "hello)

Yang pertama bisa saja fmt.Println("hello").
Duncan Jones

2

t.Logdan t.Logfmencetak dalam pengujian Anda, tetapi sering kali terlewatkan karena dicetak pada baris yang sama dengan pengujian Anda. Apa yang saya lakukan adalah membuat log dengan cara yang membuatnya menonjol, yaitu

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

    id, err := ic.FindIntercomUserAndReturnID("test3@test.com")
    assert.Nil(t, err)
    assert.NotNil(t, id)

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

yang mencetaknya ke terminal sebagai,

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

-2

The *_test.gofile sumber Go seperti yang lain, Anda dapat menginisialisasi logger baru setiap kali jika Anda perlu untuk membuang struktur data yang kompleks, di sini contoh:

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

Kemudian, setiap kali, di setiap ujian:

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()
    }*/
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.