LoginSignup
6
4

More than 5 years have passed since last update.

Go言語で標準入出力をスタブする方法

Posted at

Pipeを駆使してスタブする

結論をここに載せておきます。
https://play.golang.org/p/JtIHncxhGw

こんな感じの関数をテストしたい!って時です。

lines.go
//標準入力を行番号付きで標準出力に出力する。refer to https://golang.org/pkg/bufio/#example_Scanner_lines
func hoge() {
    i := 0
    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
        i++
        fmt.Println(i, scanner.Text()) // Println will add back the final '\n'
    }
    if err := scanner.Err(); err != nil {
        fmt.Fprintln(os.Stderr, "reading standard input:", err)
    }
}

こんな感じで書きます。

入力、出力、エラー出力をそれぞれパイプで乗っ取って、対象を実行した後、元に戻して終了。

lines_test.go
func TestHoge() {
    strout, _ := StubIO("私が標準入力だ\nガハハ", func() {
        hoge()
    })
    fmt.Println("キャプチャした標準出力")
    fmt.Println(strout)
}

// StubIO stubs Stdin Stdout Stderr in 'fn'.return Stdout and Stderr
func StubIO(inbuf string, fn func()) (string, string) {
    inr, inw, _ := os.Pipe()
    outr, outw, _ := os.Pipe()
    errr, errw, _ := os.Pipe()
    orgStdin := os.Stdin
    orgStdout := os.Stdout
    orgStderr := os.Stderr
    inw.Write([]byte(inbuf))
    inw.Close()
    os.Stdin = inr
    os.Stdout = outw
    os.Stderr = errw
    fn()
    os.Stdin = orgStdin
    os.Stdout = orgStdout
    os.Stderr = orgStderr
    outw.Close()
    outbuf, _ := ioutil.ReadAll(outr)
    errw.Close()
    errbuf, _ := ioutil.ReadAll(errr)

    return string(outbuf), string(errbuf)

}

コピペする前に

既にライブラリ化しましたので、ご自由に使ってください。

"github.com/nak1114/goutil/assert"

import(
    "github.com/nak1114/goutil/assert"
)

func TestHoge() {
    strout, _ := assert.StubIO("私が標準入力だ\nガハハ", func() {
        hoge()
    })
    fmt.Println("キャプチャした標準出力")
    fmt.Println(strout)
}

Go言語はテスト関連が弱いですね。

自前主義ではないのだけど、Rubyで言うところのWebmockやFakeFSやTimeCopも見当たらないし、その他のスタブもあまり見かけませんね。

Webmock -> Mockサーバ立てろ
FakeFS -> 仮想環境でテストしろ

までは解るのですが、TimeCopはどうしろと。dockerの時間機能をゴニョゴニョするくらいしか思いつかないです。

とりあえず、私が必要と感じたものは逐次"github.com/nak1114/goutil"に追加していこうかなと思っています。

テストフレームワークは結構好き

テスト対象と同じDirにテストを置いておくのは、行き来がしやすくて便利だと思いました。

誰かアサーション作って!

テストレポートがいい加減になるからアサーションは提供しないよってのは、作りたくないだけですよね。これも自前で比較関数作るのダルいんだけど、私のググり力が足りないので既存のが見つからないんだよなぁ。Gospelも覗いてみたけどちょっと違う。

6
4
6

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
6
4