"Test" paketini kullanarak bir Go testinde nasıl yazdırırsınız?


129

Bir şeyi yazdırmak için (yani testlerin hata ayıklaması için) Go'da bir test çalıştırıyorum ama hiçbir şey yazdırmıyor.

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

Bu dosyada go test çalıştırdığımda çıktı şu:

ok      command-line-arguments  0.004s

Bunu gerçekten yazdırmanın tek yolu, bildiğim kadarıyla, t.Error () aracılığıyla yazdırmaktır, şöyle:

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

Hangi çıktı bu:

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

Google'da araştırdım ve kılavuza baktım ama hiçbir şey bulamadım.


Bu, Go 1.14 (Q1 2010) için mümkün olabilir. Bkz aşağıda Cevabımı .
VonC

@VonC s / b Q1 2020
user2133814

@ user2133814 Kabul edildi, 2010 değil, 2020 olmalı. Aşağıdaki cevap 2020'den bahsediyor. Söz konusu cevabı, Dave Cheney'in bu yeni özellikle ilgili makalesine referansla düzenledim.
VonC

Yanıtlar:


142

Struct'lar testing.Tve testing.Bhem var .Logve .Logfses aradığınız şey olması bu yöntemi. .Logve .Logfbenzer fmt.Printve fmt.Printfsırasıyla.

Daha fazla ayrıntıya buradan bakın: http://golang.org/pkg/testing/#pkg-index

fmt.Xifadeleri yazdırmak yapmak testlerde iç işi, ama onların çıkış sen de günlük yöntemleri kullanmak neden dolayısıyla onu bulmak ve bekliyoruz ekranda değil muhtemelen bulacaksınız testing.

Sizin durumunuzda olduğu gibi, başarısız olmayan sınamaların günlüklerini görmek istiyorsanız go test, -vbayrağı (ayrıntı için v) sağlamanız gerekir . Test bayrakları hakkında daha fazla ayrıntı burada bulunabilir: https://golang.org/cmd/go/#hdr-Testing_flags


15
t.Log (), test tamamlanana kadar görünmez, bu nedenle, asılı veya kötü performans gösteren bir testin hatalarını ayıklamaya çalışıyorsanız, fmt kullanmanız gerekir. Testleri çalıştırırken fmt.Println çıktısını göstermek için go test -v kullanmak için PeterSO'nun cevabına bakın.
voutasaurus

142

Örneğin,

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

Command go

Test bayraklarının açıklaması

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

Paket testi

func (* T) Günlük

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

Günlük, Println'ye benzer şekilde varsayılan biçimlendirmeyi kullanarak bağımsız değişkenlerini biçimlendirir ve metni hata günlüğüne kaydeder. Testler için, metin yalnızca test başarısız olursa veya -test.v bayrağı ayarlanmışsa yazdırılacaktır. Karşılaştırmalar için, performansın -test.v bayrağının değerine bağlı olmasını önlemek için metin her zaman yazdırılır.


21
verbosearadığım şeydi.
cevaris

2
anwa günlük çıktısını görmek için moethod ou kendini test ediyor
filthy_wizard

7

t.Log()test tamamlanana kadar gösterilmeyecektir, bu nedenle asılı veya kötü performans gösteren bir testin hatalarını ayıklamaya çalışıyorsanız, kullanmanız gerekiyor gibi görünüyor fmt.

Evet: Go 1.13'e (Ağustos 2019) kadar olan durum buydu.

Ve bu 24929 sayısında takip edildi.golang.org

Aşağıdaki (aptalca) otomatik testleri düşünün:

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

Koşarsam go test -v, ben her dek hiçbir ölçüm sonucu elde TestFooyapılır , tüm kadar o zaman hiçbir çıkış TestBaryapılır ve tüm kadar yeniden artık çıkış TestBazyapılır.
Testler çalışıyorsa bu sorun değildir, ancak bir tür hata varsa, günlük çıktısının arabelleğe alınmasının sorunlu olduğu birkaç durum vardır:

  • Yerel olarak yinelediğimde, bir değişiklik yapabilmek, testlerimi çalıştırabilmek, neler olup bittiğini anlamak için günlüklerde neler olduğunu hemen görebilmek, gerekirse testi erken kapatmak için CTRL + C'ye basmak, başka bir değişiklik yapmak, yeniden testleri çalıştırın vb.
    Eğer TestFoo(örneğin, bir entegrasyon testi var) yavaş, çok testin sonuna kadar hiçbir ölçüm sonucu olsun. Bu, yinelemeyi önemli ölçüde yavaşlatır.
  • TestFooAskıda kalmasına ve asla tamamlanmamasına neden olan bir hata varsa , hiçbir şekilde günlük çıktısı alamam. Bu durumlarda, t.Logve t.Logfhiç bir faydası yoktur.
    Bu, hata ayıklamayı çok zorlaştırır.
  • Ayrıca, yalnızca günlük çıktısı almıyorum, aynı zamanda test çok uzun süre takılırsa, ya Go testi zaman aşımı 10 dakika sonra testi sonlandırır ya da bu zaman aşımını arttırırsam, birçok CI sunucusu da yoksa testleri sonlandırır. Belirli bir süre sonra günlük çıkışı (örneğin, CircleCI'de 10 dakika).
    Şimdi testlerim öldü ve günlüklerde bana ne olduğunu anlatacak hiçbir şey yok.

Ancak (muhtemelen) Git 1.14 (Q1 2020) için: CL 127120

test etme: ayrıntılı modda akış günlüğü çıktısı

Şimdi çıktı:

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

Dave Cheney'in " go test -vakış çıkışı " nda da onayladığı gibi, gerçekten Go 1.14'te :

Go 1.14'te, çıktıyı test çalıştırmasının sonuna kadar biriktirmek yerine , go test -vgerçekleştiği anda akışla alacaktır .t.Log

Go 1.14 altında fmt.Printlnve t.Logçizgiler vardır araya ilave ziyade zaman akış olduğunu test çıkış gösteren, tam için test için beklemek yerine, go test -vkullanılır.

Dave'e göre avantaj:

Bu, test başarısız olduğunda genellikle uzun süreler boyunca yeniden denenen entegrasyon stili testler için büyük bir yaşam kalitesi iyileştirmesidir.
Akış t.Logçıkışı, Gophers'ın çıktılarını almak için tüm testin zaman aşımına uğramasını beklemek zorunda kalmadan bu test hatalarını gidermesine yardımcı olur.


5

Bazen test etmek için yaparım

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

Ayrıca şunlara yazdırabilirsiniz:

fmt.Fprintln(os.Stderr, "hello)

Bunlardan ilki sadece olabilir fmt.Println("hello").
Duncan Jones

2

t.Logve t.Logftestinizin çıktısını alın, ancak testinizle aynı satıra yazdırdığı için genellikle gözden kaçabilir. Yaptığım şey, onları öne çıkaracak şekilde günlüğe kaydetmektir.

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

terminale yazdırır,

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

*_test.goDosya, karmaşık veri yapısını, burada bir örnek dökümü gerekiyorsa diğerleri gibi git kaynağı, yeni bir logger her zaman başlatabilir geçerli:

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

Sonra her seferinde her testte:

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()
    }*/
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.