「testing」パッケージを使用して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

私はグーグルで検索してマニュアルを調べましたが、何も見つかりませんでした。


これはGo 1.14(2010年第1四半期)の可能性があります。以下の私の答えを参照しください。
VonC、

@VonC s / b 2020
user2133814

@ user2133814同意しました、それは2010年ではなく、確かに2020年である必要があります。以下回答は2020年について言及しています。その新しい機能に関するDave Cheneyの記事を参照して、この回答を編集しました。
VonC

回答:


142

構造体testing.Ttesting.B両方には、あなたが探しているものであるように聞こえるa メソッド.Log.Logfメソッドがあります。.Log.Logfに類似しているfmt.Printfmt.Printf、それぞれ。

詳細はこちら:http : //golang.org/pkg/testing/#pkg-index

fmt.X印刷ステートメントテスト内で機能しますが、出力が画面に表示されていないことがわかります。そのため、でロギングメソッドを使用する必要がありますtesting

あなたの場合のように、失敗していないテストのログを表示したい場合はgo test-vフラグ(冗長性の場合はv)を指定する必要があります。フラグのテストの詳細については、https//golang.org/cmd/go/#hdr-Testing_flagsをご覧ください。


15
t.Log()はテストが完了するまで表示されないため、ハングしているテストまたはパフォーマンスが悪いテストをデバッグしようとする場合は、fmtを使用する必要があるようです。テストの実行時にfmt.Printlnの出力を表示するためのgo test -vの使用については、PeterSOの回答を参照してください。
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{})

Logは、Printlnに類似したデフォルトのフォーマットを使用して引数をフォーマットし、エラーログにテキストを記録します。テストの場合、テキストは、テストが失敗した場合、または-test.vフラグが設定されている場合にのみ出力されます。ベンチマークの場合、パフォーマンスが-test.vフラグの値に依存しないように、テキストは常に印刷されます。


21
verbose私が探していたものです。
cevaris 2014

2
anethがmoethod ouでログ出力を表示するために自分自身をテストしています
filthy_wizard 16/07/23

7

t.Log()テストが完了するまで表示されないので、ハングしているテストやパフォーマンスが悪いテストをデバッグする場合は、を使用する必要がありますfmt

はい:Go 1.13(2019年8月)まで含まれていました。

そしてそれは問題24929で続いたgolang.org

次の(ばかげた)自動テストを検討してください。

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.Logt.Logfまったく役に立ちません。
    これはデバッグを非常に困難にします。
  • さらに、ログ出力が得られないだけでなく、テストがハングしすぎると、Goテストのタイムアウトにより10分後にテストが強制終了されるか、タイムアウトを長くすると、多くのCIサーバーでもテストが強制終了されます一定時間後のログ出力(たとえば、CircleCIでは10分)。
    だから今私のテストは殺され、何が起こったのかを伝えるためのログには何もありません。

しかし、(おそらく)Go 1.14(2020年第1四半期)の場合:CL 127120

テスト:詳細モードでのストリームログ出力

出力は次のとおりです。

=== 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 test -vストリーミング出力」で証明しているように、それは実際にGo 1.14にあります

Go 1.14では、テスト実行の最後まで蓄積するのではなく、出力を発生時にgo test -vストリーミングしt.Logます。

Go 1.14 では、テストが完了するのを待つのではなくfmt.Printlnt.Logラインがインターリーブgo test -vされます。これは、テスト出力がが使用されるときにストリーミングされることを示しています。

デイブによると、利点:

これは、テストが失敗したときに長期間にわたって再試行することが多い統合スタイルのテストでの生活の質を大幅に改善します。
ストリーミングt.Log出力は、Gopherがテスト全体がタイムアウトして出力を受信するまで待つ必要なく、テストの失敗をデバッグするのに役立ちます。



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ファイルは他のファイルと同様に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.