Goのlogパッケージや標準出力内容の結果をテストをしたいときのメモ。
ログ出力のテスト
Goのlogパッケージのlog.PrintXX
のログ出力先はデフォルトではos.Stderr
ですが、log.SetOutputによって出力先を変更することができます。
log.SetOutput
func SetOutput(w io.Writer)
テストする関数は以下の通りです。
trysail.go
type member int
const (
mocho member = iota
sora
nansu
)
func printLog(m member) {
switch m {
case mocho:
log.Print("(o・∇・o)終わりだよ〜")
case sora:
log.Print("(°Q`)")
case nansu:
log.Print("(*>△<)<ナーンナーンっっ")
}
}
引数によって出力するログの内容が変わる単純な関数です。
ではテストコードを書いてみましょう
trysail_test.go
func Test_printLog(t *testing.T) {
// ログの出力先をバッファに変更
var buf bytes.Buffer
log.SetOutput(&buf)
// デフォルトだと日付が出力されてしまうので、フラグに0を設定する
defaultFlags := log.Flags()
log.SetFlags(0)
// Test_printLogテスト終了時、変更した内容を戻す
defer func() {
log.SetOutput(os.Stderr)
log.SetFlags(defaultFlags)
}()
t.Run("Mocho", func(t *testing.T) {
// 次のテスト(Nansu)に影響がないように、Mochoテスト終了時にバッファの内容をクリアする
defer func() {
buf.Reset()
}()
printLog(mocho)
expected := "(o・∇・o)終わりだよ〜"
// 末尾に改行コードが入っているので除去する
actual := strings.TrimRight(buf.String(), "\n")
if actual != expected {
t.Fatalf("failed! actual = %s, expected = %s", actual, expected)
}
})
t.Run("Nansu", func(t *testing.T) {
defer func() {
buf.Reset()
}()
printLog(nansu)
expected := "(*>△<)<ナーンナーンっっ"
actual := strings.TrimRight(buf.String(), "\n")
if actual != expected {
t.Fatalf("failed! actual = %s, expected = %s", actual, expected)
}
})
}
標準出力のテスト
なんと、Go言語の標準出力や標準入力であるos.Stdout
やos.Stderr
はos.File
で上書きすることができます。マジかよ…
os.File
をbytes.Buffer
につなぐためにos.Pipe
を利用します。
テストする関数は以下の通りです。
trysail.go
type member int
const (
mocho member = iota
sora
nansu
)
func print(m member) {
switch m {
case mocho:
fmt.Println("(o・∇・o)終わりだよ〜")
case sora:
fmt.Println("(°Q`)")
case nansu:
fmt.Println("(*>△<)<ナーンナーンっっ")
}
}
先ほどの関数のfmt.Println
版です。
fmt.Println
はos.Stdout
に書き込むので、そちらをbytes.Buffer
にPipeします。
func Test_print(t *testing.T) {
tmpStdout := os.Stdout
defer func() {
os.Stdout = tmpStdout
}()
t.Run("Mocho", func(t *testing.T) {
r, w, _ := os.Pipe()
os.Stdout = w
print(mocho)
w.Close() // クローズしないと永遠に読み込み待ち状態になるよ
var buf bytes.Buffer
buf.ReadFrom(r)
expected := "(o・∇・o)終わりだよ〜"
actual := strings.TrimRight(buf.String(), "\n")
if actual != expected {
t.Fatalf("failed! actual = %s, expected = %s", actual, expected)
}
})
t.Run("Nansu", func(t *testing.T) {
r, w, _ := os.Pipe()
os.Stdout = w
print(nansu)
w.Close()
var buf bytes.Buffer
buf.ReadFrom(r)
expected := "(*>△<)<ナーンナーンっっ"
actual := strings.TrimRight(buf.String(), "\n")
if actual != expected {
t.Fatalf("failed! actual = %s, expected = %s", actual, expected)
}
})
}
意外と簡単にできた。
(o・∇・o)終わりだよ〜