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

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

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.