5
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
5
Help us understand the problem. What are the problem?