Posted at
Go2Day 12

Goで標準出力をキャプチャするパッケージを書いた

More than 1 year has passed since last update.

Go2 Advent Calendar 2017 12日目の記事です。

昨日たまたま空きを見つけたので代筆させていただきます。


はじめに

先日Go4 Advent Calendar 2017 2日目でGoで標準出力をテストする方法という記事を書きました。

要約すると、理想的には fmt.Fprint() などで io.Writer を渡す形でテスタブルに実装した方がよいが、都合上できない場合は os.Stdout を差し替えてそれを読むようにすればよい、という内容です。

ただこれを毎回実装するのも面倒なので、パッケージとして公開しました。


使い方

パッケージの使い方はREADMEやgodocのとおりですが、以下に例を示します。

先日の記事では、次のようなコードに対してテストを実装しました。

main.go:

package main

import (
"flag"
"fmt"
"os"
)

const (
ExitCodeOK = iota
ExitCodeError
)

func main() {
os.Exit(run(os.Args[1:]))
}

func sum(x, y int) int {
return x + y
}

func run(args []string) int {
var x, y int

flags := flag.NewFlagSet("sum", flag.ContinueOnError)
flags.IntVar(&x, "x", 0, "Value for x")
flags.IntVar(&y, "y", 0, "Value for y")
flags.Parse(args)

fmt.Printf("%d + %d = %d\n", x, y, sum(x, y))

return ExitCodeOK
}

この標準出力をともなう main() に対するテストは、go-capturerを用いると次のように書けます。

main_test.go:

package main

import (
"testing"

"github.com/kami-zh/go-capturer"
)

func TestRun(t *testing.T) {
var code int

out := capturer.CaptureStdout(func() {
code = run([]string{"-x", "2", "-y", "3"})
})

if code != ExitCodeOK {
t.Errorf("Unexpected exit code: %d", code)
}

if out != "2 + 3 = 5\n" {
t.Errorf("Unexpected output: %s", out)
}
}

標準出力だけでなく標準エラー出力も取得でき、また上のように関数の返り値も得ることができます。


思ったこと

今回はじめてGoのパッケージをつくったのですが、


  • GitHubにリポジトリを追加してREADMEを書くだけでgodocができており、さらにExampleなどもあってすごい


  • go reportという外部サービスでgofmtやgolintによるチェックとを行ってくれるので便利

という感想を持ちました。


筆者アカウント: Twitter, GitHub