概要
golang で fmt や log で標準出力に出したログの文字列をテストする方法を紹介します
少しポイントがあるのでそこも紹介します
環境
- macOS 10.15.2
- golang 1.12.9
メインコード
今回はロギングに kitlog を使っています
標準の log パッケージでも問題ないですが kitlog を使う場合は事前にインストールしておきましょう
go get github.com/go-kit/kit/log
vim $GOPATH/github.com/hawksnowlog/hoge/hoge.go
package hoge
import (
"fmt"
"github.com/go-kit/kit/log"
"os"
)
type Hoge struct {
logger log.Logger
}
func NewHoge() *Hoge {
w := log.NewSyncWriter(os.Stdout)
logger := log.NewLogfmtLogger(w)
return &Hoge{logger}
}
func (h *Hoge) LoggingByKitlog() {
name := "hawksnowlog"
age := 99
h.logger.Log("name", name, "age", age)
}
func (h *Hoge) LoggingByFmt() {
fmt.Println("name=hawksnowlog age=88")
}
テストコード
vim $GOPATH/github.com/hawksnowlog/hoge/hoge_test.go
package hoge
import (
"bytes"
"io"
stdlog "log"
"os"
"sync"
"testing"
)
func captureOutput(f func()) string {
reader, writer, err := os.Pipe()
if err != nil {
panic(err)
}
stdout := os.Stdout
stderr := os.Stderr
defer func() {
os.Stdout = stdout
os.Stderr = stderr
stdlog.SetOutput(os.Stderr)
}()
os.Stdout = writer
os.Stderr = writer
stdlog.SetOutput(writer)
out := make(chan string)
wg := new(sync.WaitGroup)
wg.Add(1)
go func() {
var buf bytes.Buffer
wg.Done()
io.Copy(&buf, reader)
out <- buf.String()
}()
wg.Wait()
f()
writer.Close()
return <-out
}
func TestHoge_Logging(t *testing.T) {
// h := NewHoge() ここだとエラーになる
output := captureOutput(func() {
h := NewHoge()
//h.LoggingByFmt()
h.LoggingByKitlog()
})
if output != "name=hawksnowlog age=99\n" {
t.Errorf("error: %s", output)
}
}
実行
go fmt github.com/hawksnowlog/hoge && go test -v github.com/hawksnowlog/hoge
ポイント
captureOutput
という関数に標準出力する処理を渡します
渡した処理内で出力されるログが文字列として返ってきます
ポイントは Hoge 構造体を作成するのも captureOutput
の中で行う点です
もし captureOutput
の外で h := NewHoge()
すると Hoge 構造体でロギングしている情報がうまく取得できません
また比較する際に改行コードなどのエスケープ文字にも注意してください
タブ区切りでログを出力している場合にはタブ文字 (\t
) が入ります
標準出力をキャプチャする関数はこれ以外にもたくさん紹介されていますがどれも仕組み的には同じです
0 件のコメント:
コメントを投稿