2014/06/25

Go言語のBDDテストツールGoConveyを使ってみる

Goのtestingパッケージが割と使いづらく感じていて、BDDっぽく書けないものかと調べていたら、GoConveyというBDDテストツールがよさそうだったので使ってみました。

  • コマンドラインgo testをそのまま使える
  • Web UIを持っている
  • WebNotificationによるデスクトップ通知ができる
  • コードカバレッジを出してくれる
  • ファイルを監視して、更新したときにテストを自動的に実行してくれる
  • テキストからテストケースの雛形を生成してくれる

他のGoの各テストフレームワークとの比較には、こちらの機能比較表も参照ください。

インストール

インストールはgo getするだけです。

$ go get -t github.com/smartystreets/goconvey

Web UIの起動

$GOPATH/bin/goconveyでテストサーバが起動します。

$ $GOPATH/bin/goconvey
2014/06/21 22:23:50 goconvey.go:54: Initial configuration: [host: 127.0.0.1] [port: 8080] [poll: 250ms] [cover: true] [short: false]
2014/06/21 22:23:50 goconvey.go:93: Constructing components...
2014/06/21 22:23:50 watcher.go:32: Adjusting to watch new root: /Users/safx/src/Sample/gosamle
2014/06/21 22:23:50 watcher.go:42: Including: /Users/safx/src/Sample/gosamle
2014/06/21 22:23:50 tester.go:16: Now configured to test 10 packages concurrently.
2014/06/21 22:23:50 watcher.go:80: Number of watched folders: 1
2014/06/21 22:23:50 goconvey.go:85: Serving HTTP at: http://127.0.0.1:8080
2014/06/21 22:23:50 monitor.go:16: Engaging monitoring loop...
2014/06/21 22:23:50 scanner.go:32: Updating root in scanner: /Users/safx/src/Sample/gosamle
2014/06/21 22:23:50 watcher.go:80: Number of watched folders: 1
2014/06/21 22:23:50 monitor.go:44: Preparing for test run (watching 1 folders)...
2014/06/21 22:23:50 executor.go:69: Executor status: 'executing'
2014/06/21 22:23:50 coordinator.go:39: Executing concurrent tests: Sample/gosamle
2014/06/21 22:23:50 parser.go:20: [no go code]: Sample/gosamle
2014/06/21 22:23:50 executor.go:69: Executor status: 'idle'
2014/06/21 22:23:50 monitor.go:47: Test run complete, updating server with latest output...
2014/06/21 22:23:50 monitor.go:50: Server updated with 1 tested packages (revision: '2014-06-21 22:23:50.502114931 +0900 JST').

起動後にlocalhost:8080にアクセスすれば、次のようなページが表示されます。

Composer

テストを最初から作る場合には、コンポーザを利用しましょう。右上の鉛筆ボタンでコンポーザタブが開きます。

ここの左側に次のような感じでテスト内容を書いていけば、リアルタイムで右側にテストコードの雛形が作られます。

  • タブインデントなしで「Test」で始まる行はテスト関数になる
  • タブインデントのある行はスコープになる

詳細はコンポーザのヘルプを参照してください。

ちなみに上では、例として16進数の文字列から数値に変換する関数に対するテストを書いています。

テストを書いてみる

コンポーザで作った雛形をsample_test.goに張りつけて、テストを書いていきます。

Convey("数字とa〜fだけの文字列のときは数値を返す", t, nil)

となっているところを、

Convey("数字とa〜fだけの文字列のときは数値を返す", t, func() {
    r, _ := HexStringToInteger("0")
    So(r, ShouldEqual, 0)
}

とします。Soは英語の接続詞の「だから」です。ShouldEqualはGoConveyのアサーションです。

この場合だと、「数字とa〜fだけの文字列のときは数値を返す。だから入力"0"のときの出力は0になるべきだ」くらいの意味になります。

ちなみに、複数の戻り値がある場合にSoでうまく受ける方法がわからなかったので、一時変数を利用しています (HexStringToInteger(int, error)を返すつもり)。

ファイルを保存すると自動でコンパイルが始まって、ビルドに失敗します。テストされる側の関数を書いていないので当り前です。

テストされる関数HexStringToIntegerをてきとうに次のように書きます。

func HexStringToInteger(s string) (int, error) {
    return 0, nil
}

とりあえず成功するようになりました。

なので、テストケース追加です。

Convey("数字とa〜fだけの文字列のときは数値を返す", t, func() {
    r, _ := HexStringToInteger("0")
    So(r, ShouldEqual, 0)

    r, _ := HexStringToInteger("1")
    So(r, ShouldEqual, 1)
}

今度は失敗しました。

このテストを通るようにしましょう。後のことを考えてforswitchを使うようにしてみました。

func HexStringToInteger(s string) (int, error) {
    num := 0
    for _, j := range(s) {
        switch {
        case '0' <= j && j <= '9': num = num * 16 + int(j - '0')
        }
    }
    return num, nil
}

……みたいなことを繰り返して実装していきます。

その他の機能

テストが通った場合にはカバレッジが棒グラフで表示されます。さらに、クリックでソースコードも表示されるはずですが、手元の環境では404になって見ることができませんでした。

また、時計ボタンでテスト結果の履歴を見ることもできます。

その隣の鐘ボタンをトグルしておくと、WebNotification可能なブラウザでは通知ウィンドウが表示されるようになります。

おわりに

GoConveyの使い方を簡単に紹介しました。

GoConveyの紹介ビデオ (約4分)はFizzBuzzを例にしたわかりやすいGoConveyの紹介なので、こちらも見ておくとよいでしょう。

関連項目

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。