คุณจะพิมพ์ในการทดสอบ Go โดยใช้แพ็คเกจ "การทดสอบ" ได้อย่างไร?


129

ฉันกำลังทำการทดสอบใน Go พร้อมกับคำสั่งเพื่อพิมพ์บางสิ่ง (เช่นสำหรับการดีบักการทดสอบ) แต่มันไม่ได้พิมพ์อะไรเลย

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

เมื่อฉันเรียกใช้ go test กับไฟล์นี้นี่คือผลลัพธ์:

ok      command-line-arguments  0.004s

วิธีเดียวที่จะทำให้มันพิมพ์ได้จริงเท่าที่ฉันรู้คือการพิมพ์ผ่าน t.Error () ดังนี้:

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

ซึ่งผลลัพธ์นี้:

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 และดูคู่มือ แต่ไม่พบอะไรเลย


สิ่งนี้อาจเป็นไปได้สำหรับ Go 1.14 (Q1 2010) ดูคำตอบของฉันด้านล่าง
VonC

@VonC s / b Q1 2020
user2133814

@ user2133814 เห็นด้วยควรเป็นปี 2020 ไม่ใช่ปี 2010 คำตอบด้านล่างกล่าวถึงปี 2020 ฉันได้แก้ไขคำตอบดังกล่าวโดยอ้างอิงถึงบทความของ Dave Cheney เกี่ยวกับคุณสมบัติใหม่นั้น
VonC

คำตอบ:


142

โครงสร้างtesting.Tและtesting.Bทั้งสองมี a .Logและ.Logfวิธีการที่เหมาะกับสิ่งที่คุณกำลังมองหา .Logและ.Logfมีความคล้ายคลึงfmt.Printและfmt.Printfตามลำดับ

ดูรายละเอียดเพิ่มเติมที่นี่: http://golang.org/pkg/testing/#pkg-index

fmt.Xพิมพ์งบทำทดสอบภายในงาน testingแต่คุณจะได้พบกับผลผลิตของพวกเขาอาจจะไม่ได้อยู่บนหน้าจอที่คุณคาดหวังที่จะพบว่ามันและดังนั้นเหตุผลที่คุณควรใช้วิธีการเข้าสู่ระบบใน

ถ้าเป็นในกรณีของคุณคุณต้องการที่จะเห็นการบันทึกสำหรับการทดสอบที่ไม่ได้ล้มเหลวคุณจะต้องให้ธง (V สำหรับฟุ่มเฟื่อย) สามารถดูรายละเอียดเพิ่มเติมเกี่ยวกับแฟล็กการทดสอบได้ที่นี่: https://golang.org/cmd/go/#hdr-Testing_flagsgo test-v


15
t.Log () จะไม่ปรากฏจนกว่าการทดสอบจะเสร็จสมบูรณ์ดังนั้นหากคุณกำลังพยายามดีบักการทดสอบที่หยุดทำงานหรือทำงานไม่ดีดูเหมือนว่าคุณต้องใช้ fmt ดูคำตอบของ PeterSO สำหรับการใช้ go test -v เพื่อแสดงเอาต์พุตของ fmt.Println เมื่อทำการทดสอบ
voutasaurus

142

ตัวอย่างเช่น,

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

สั่งไป

คำอธิบายของแฟล็กการทดสอบ

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

การทดสอบแพ็คเกจ

บันทึก func (* T)

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

บันทึกจัดรูปแบบอาร์กิวเมนต์โดยใช้การจัดรูปแบบเริ่มต้นคล้ายกับ Println และบันทึกข้อความในบันทึกข้อผิดพลาด สำหรับการทดสอบข้อความจะถูกพิมพ์เฉพาะเมื่อการทดสอบล้มเหลวหรือตั้งค่าแฟล็ก -test.v สำหรับการวัดประสิทธิภาพข้อความจะถูกพิมพ์เสมอเพื่อหลีกเลี่ยงการมีประสิทธิภาพขึ้นอยู่กับค่าของแฟล็ก -test.v


21
verboseคือสิ่งที่ฉันกำลังมองหา
cevaris

2
anwa เพื่อดูเอาต์พุตบันทึกใน moethod ou กำลังทดสอบตัวเอง
filthy_wizard

7

t.Log()fmtจะไม่แสดงขึ้นจนกระทั่งหลังจากการทดสอบเสร็จสมบูรณ์ดังนั้นถ้าคุณกำลังพยายามที่จะแก้ปัญหาการทดสอบที่จะแขวนหรือทำงานได้ไม่ดีดูเหมือนว่าคุณจำเป็นต้องใช้

ใช่: ในกรณีนี้รวมถึง Go 1.13 (สิงหาคม 2019)

และตามมาในgolang.orgฉบับ 24929

พิจารณาการทดสอบอัตโนมัติ (โง่ ๆ ) ต่อไปนี้:

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

ถ้าผมทำงานgo test -v, ฉันได้รับการส่งออกบันทึกจนกว่าทั้งหมดTestFooจะทำแล้วไม่มีเอาท์พุทจนทุกTestBarจะทำและส่งออกอีกครั้งไม่มากจนทุกTestBazจะทำ
วิธีนี้ใช้ได้ดีหากการทดสอบใช้งานได้ แต่หากมีข้อผิดพลาดบางประเภทมีบางกรณีที่เอาต์พุตบันทึกการบัฟเฟอร์มีปัญหา:

  • เมื่อทำซ้ำในเครื่องฉันต้องการที่จะทำการเปลี่ยนแปลงเรียกใช้การทดสอบของฉันดูว่าเกิดอะไรขึ้นในบันทึกทันทีเพื่อทำความเข้าใจว่าเกิดอะไรขึ้นกด CTRL + C เพื่อปิดการทดสอบก่อนเวลาหากจำเป็นทำการเปลี่ยนแปลงใหม่อีกครั้ง เรียกใช้การทดสอบและอื่น ๆ
    ถ้าTestFooช้า (เช่นเป็นการทดสอบการรวม) ฉันจะไม่ได้รับเอาต์พุตบันทึกจนกว่าจะสิ้นสุดการทดสอบ สิ่งนี้ทำให้การทำซ้ำช้าลงอย่างมาก
  • หากTestFooมีข้อผิดพลาดที่ทำให้แฮงค์และไม่สมบูรณ์ฉันจะไม่ได้รับเอาต์พุตบันทึกใด ๆ ในกรณีเหล่านี้t.Logและt.Logfไม่มีประโยชน์เลย
    ทำให้การดีบักทำได้ยากมาก
  • ยิ่งไปกว่านั้นไม่เพียง แต่ฉันจะไม่ได้รับเอาต์พุตบันทึกเท่านั้น แต่หากการทดสอบหยุดทำงานนานเกินไปการหมดเวลาทดสอบ Go จะฆ่าการทดสอบหลังจากผ่านไป 10 นาทีหรือถ้าฉันเพิ่มระยะหมดเวลานั้นเซิร์ฟเวอร์ CI จำนวนมากจะปิดการทดสอบด้วยหากไม่มี บันทึกเอาต์พุตหลังจากระยะเวลาหนึ่ง (เช่น 10 นาทีใน CircleCI)
    ตอนนี้การทดสอบของฉันถูกฆ่าตายและฉันไม่มีอะไรในบันทึกที่จะบอกว่าเกิดอะไรขึ้น

แต่สำหรับ (อาจเป็นไปได้) ไป 1.14 (Q1 2020): CL 127120

การทดสอบ: สตรีมล็อกเอาต์พุตในโหมด verbose

ผลลัพธ์ตอนนี้คือ:

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

มันอยู่ใน Go 1.14 อย่างที่ Dave Cheney ยืนยันใน " go test -vสตรีมมิ่งเอาท์พุต ":

ใน Go 1.14 go test -vจะสตรีมt.Logเอาต์พุตตามที่เกิดขึ้นแทนที่จะกักตุนไว้จนกว่าจะสิ้นสุดการทดสอบที่มันเกิดขึ้นมากกว่าการกักตุนมันถึงจุดสิ้นสุดของการดำเนินการทดสอบ

ภายใต้ Go 1.14 fmt.Printlnและt.Logบรรทัดจะแทรกสลับกันแทนที่จะรอให้การทดสอบเสร็จสมบูรณ์แสดงให้เห็นว่าเอาต์พุตการทดสอบถูกสตรีมเมื่อgo test -vใช้งาน

ข้อได้เปรียบตาม Dave:

นี่คือการปรับปรุงคุณภาพชีวิตที่ดีสำหรับการทดสอบรูปแบบการบูรณาการซึ่งมักจะลองซ้ำเป็นเวลานานเมื่อการทดสอบล้มเหลว เอาต์พุตการ
สตรีมt.Logจะช่วยให้ Gophers แก้ไขข้อบกพร่องของการทดสอบเหล่านั้นโดยไม่ต้องรอจนกว่าการทดสอบทั้งหมดจะหมดเวลาเพื่อรับเอาต์พุต


5

สำหรับการทดสอบบางครั้งฉันทำ

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

นอกจากนี้คุณสามารถพิมพ์ไปที่:

fmt.Fprintln(os.Stderr, "hello)

คนแรกสามารถเป็นfmt.Println("hello")ได้
Duncan Jones

2

t.Logและt.Logfพิมพ์ออกมาในการทดสอบของคุณ แต่มักจะพลาดเนื่องจากพิมพ์ในบรรทัดเดียวกับการทดสอบของคุณ สิ่งที่ฉันทำคือบันทึกพวกเขาด้วยวิธีที่ทำให้พวกเขาโดดเด่นนั่นคือ

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

ซึ่งพิมพ์ไปยังเทอร์มินัลเป็น

=== 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.goไฟล์เป็นแหล่งที่ไปเหมือนคนอื่น ๆ ที่คุณสามารถเริ่มต้นตัดไม้ใหม่ทุกครั้งถ้าคุณจำเป็นต้องถ่ายโอนข้อมูลโครงสร้างข้อมูลที่ซับซ้อนที่นี่ตัวอย่าง:

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

จากนั้นทุกครั้งในการทดสอบทุกครั้ง:

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()
    }*/
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.