LoginSignup
11
5

More than 5 years have passed since last update.

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

Posted at

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

11
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
5