Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

Pipeを駆使してスタブする

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

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

https://golang.org/pkg/bufio/#example_Scanner_lines

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も覗いてみたけどちょっと違う。

nak1114
Webの浅瀬で遊んでいます
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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした