【Go】go test でテストしよう

f:id:suganoo:20190111143332p:plain
Goでちゃんとテストコードを書こうとようやく重い腰をあげてみました。

コーディングしてるとテストコードは後回しにしてしまうんですよね。ちゃんとやってみます。後回しにするの良くないっすね(汗)。。。

go testについて調べたことを記事にしてみようと思います。

基本的な実行方法

サンプルコード

こんなコードを用意してみます。

hoge.go
hoge_test.go
fuga_test.go

hoge.go

package main

import (
        "fmt"
)

func hogefunc() int {
        return 1
}

func fugafunc() int {
        return 2
}

func main() {
        fmt.Println(hogefunc())
        fmt.Println(fugafunc())
}

hoge_test.go

package main

import (
        "testing"
)

func TestHogefunc(t *testing.T){
        n := hogefunc()
        if n != 1 {
                t.Fatal("Error return num")
        }
}

fuga_test.go

package main

import (
        "testing"
)

func TestFugafunc(t *testing.T){
        n := fugafunc()
        if n != 2 {
                t.Fatal("Error return num")
        }
}
注意点

気をつけたいところとして下記があります。

  • テストファイルのファイル名は「_test.go」で終わること。
  • テストコードのテスト関数は「TestXxxx」の形式にすること。

2番目の方は一度、「Testgethoge...」とか書いてしまいなんでテストが実行されないんだ?っと悩んでしまいました。正確に書きましょう「TestGethoge...」ですね。

実行とオプション

  • -v -coverつけておこう。

実行コマンドです。

go test

ですが、下記パラメータをオススメします。

go test -v -cover

っというのも出力結果が変わってくるからです。

なにもオプションをつけないとこうなります。

go test

PASS
ok      _/xxxxxxxxxxxx 0.293s

が、オプションつけるとこうなります。

go test -v -cover

=== RUN   TestFugafunc
--- PASS: TestFugafunc (0.00s)
=== RUN   TestHogefunc
--- PASS: TestHogefunc (0.00s)       <--- -v のおかげ
PASS
coverage: 50.0% of statements       <---- -coverのおかげ
ok      /xxxxxxxxxxxxxxx 0.296s

テスト関数の指定

特定のテスト関数だけを実行することも可能です

go test -v -cover -run TestHogefunc

ここなんですけど、じゃあ特定の2つのテスト関数やりたいときどうすればいいのか?と考えたんですが、あまりスマートにできそうにありませんでした。

どうも -run 以降は正規表現で指定するようで、特定の複数のテスト関数を指定したいときは正規表現で指定するしかないようです。

go test  -v -cover -run Test.*func

とか。

特定のテストファイルだけ

特定のテストファイルだけを実行したいときは下記のようにします。

go test -v -cover hoge_test.go hoge.go

この時 hoge.go ファイルを抜かしてしまうと下記のようなエラーになります。

go test -v -cover hoge_test.go
# command-line-arguments [command-line-arguments.test]
.\hoge_test.go:8:7: undefined: hogefunc
FAIL    command-line-arguments [build failed]

hogefunc関数がねーよと。

もっとオプション

様々なオプション

上記のオプションはごく一部でして、まだたくさんあります。
下記のコマンドを実行すればいろいろ出てきます。

go help testflag

coverage?

上記のcoverageの結果なんですが、ちょっと気になったところがありました。

coverage: 50.0% of statements    

50%ってどういうことなんだ?どこからこういう計算をしてるんでしょう?

下記のコマンドを実行するとcoverrageの結果をブラウザで確認することができます。

go test -v -coverprofile output
go tool cover -html=output -o cover.html

このcover.htmlをブラウザで確認してみます。
f:id:suganoo:20190111113026p:plain
なるほど、実行してる関数の内50%しか確認してないことがわかりますね。

引数ある場合どうする?

  • -args つける!

スクリプトを実行する際に引数を必要とすることもあります。

例えば、flagを使ってその引数にconfファイルを設定してて、そのファイルの中の値を取得する関数があったとします。テスト実行時に引数としてファイルが必要になりますよね。

そんなときには -args が使えます。

引数が必要なサンプルコード 引数無くても動いちゃうんだけど、そこは勘弁。。。

package main

import (
        "flag"
        "fmt"
        "os"
)

var (
        argC = flag.String("c", "default", "config file path")
)

func hogefunc() int {
        return 1
}

func fugafunc() int {
        return 2
}

func ini() {
        // read config file
        flag.Parse()
        conf := *argC
        fmt.Println(conf)
        if conf == "default" {
                os.Exit(1)
        }

}

func main() {
        fmt.Println(hogefunc())
        fmt.Println(fugafunc())
}

実行はこんな感じ

go run hoge.go -c conf.txt

テスト実行コマンドはこうなります。

go test -v -cover -args -c confighoge

最後

(SEOのために試しに書いてみる)「いかがでしたか?」

ここでも「Goプログラミング実践入門」が役に立ちました。
あの本の中にはUnitテストやHttpのテスト、ベンチマークテストも書かれており、ざっくりGoのテストを理解するためにかなり役立ちました。
けっこう優秀だな!

Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る impress top gearシリーズ

Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る impress top gearシリーズ

blog.suganoo.net
blog.suganoo.net


で、こんな記事を書いてて「みんなのGo言語」を立ち読みしたら、俺の知りたいことほとんど書いてあった。。。
ある程度知識や経験が溜まってくると「みんなのGo言語」はかなりいい本だなと再認識してきます。
オススメです。

みんなのGo言語【現場で使える実践テクニック】

みんなのGo言語【現場で使える実践テクニック】