Spockを使ってみた

G*界隈でよく聞くテスティングフレームワークのSpockを使ってみました。
名前や記事は良く見てたのですが、JUnit自体を殆ど使用していなかったので実践はしていませんでした。
が、JUnitをいくらか勉強してみたら興味がわいたので試してみた次第。

前提

IDE : Eclipse
Groovyプラグイン導入済み
Groovyプロジェクト作成済み

jarの取得

参考にしたサイトではGroovyのバージョンがV2.Xだと動かないと書いてあったので、spockの新バージョンを探す。
あった。
1.8用と2.0用があったので2.0用を選択。

Central Repository: org/spockframework/spock-core/0.7-groovy-2.0

  1. spock-core-0.7-groovy-2.0-sources.jar
  2. spock-core-0.7-groovy-2.0.jar

この2つのjarを取得。

ビルドパスに追加。

取得したspock-core-0.7-groovy-2.0.jarをビルドパスに追加。
ソースとしてspock-core-0.7-groovy-2.0.jarを指定しとくと尚良し。

サンプル実行

Spockのサンプル実行。
相変わらずカッコイイ!
Google Code Archive - Long-term storage for Google Code Project Hosting.

class HelloSpock extends spock.lang.Specification {
    def "length of Spock's and his friends' names"() {
        expect:
        name.size() == length

        where:
        name     | length
        "Spock"  | 5
        "Kirk"   | 4
        "Scotty" | 6
    }
} 

実践

文字列を計算するというお題をやってたのでそれのテストを記述。
サンプルと同じようにやってもしょうがないので、例外のテストと、パラメータをテストケースに埋め込む方法も試してみた。
参考 : mike、mikeなるままに…: Spockで例外のテスト

@RunWith(Enclosed)
class CalcTest {
    public static class 括弧なし_正常処理 extends Specification {
        @Unroll
        def "calculationへの入力値が #value の時は #expected が返される" () {
            expect   :
            new Calc().calculation(value) == expected

            where  :
            value    | expected
            "1"      | 1
            "12"     | 12
            "1+2"    | 3
            "3-2"    | 1
            "2*3"    | 6
            "6/3"    | 2
            "1+2+3"  | 6
            "3+2-1"  | 4
            "3*4-1"  | 11
            "4/2-1"  | 1
            "1+3*4"  | 13
            "1+4/2"  | 3
        }
    }
    public static class 入力チェック例外 extends Specification {

        @Unroll
        def "calculationの入力値が #value の時には #exception が投げられる" () {
            when   :
            new Calc().calculation(value)

            then   :
            def e = thrown(exception)
            assert e.class == exception
            assert e.message == message

            where  :
            value     | exception                | message
            null      | IllegalArgumentException | "入力値は数値か+-*/()のみです。 入力値 : [null]"
            ""        | IllegalArgumentException | "入力値は数値か+-*/()のみです。 入力値 : []"
            "+"       | IllegalArgumentException | "入力値は数値か+-*/()のみです。 入力値 : [+]"
            " 1 + 2 " | IllegalArgumentException | "入力値は数値か+-*/()のみです。 入力値 : [ 1 + 2 ]"
            "3 + 4"   | IllegalArgumentException | "入力値は数値か+-*/()のみです。 入力値 : [3 + 4]"
            "+1+2"    | IllegalArgumentException | "入力値は数値か+-*/()のみです。 入力値 : [+1+2]"
            "1+2+"    | IllegalArgumentException | "入力値は数値か+-*/()のみです。 入力値 : [1+2+]"
        }
    }
    public static class 括弧あり_正常処理 extends Specification {
        @Unroll
        def "calculationへの入力値が #value の時は #expected が返される" () {
            expect   :
            new Calc().calculation(value) == expected

            where  :
            value                             | expected
            "2*(1+3)"                         | 8
            "8/(3+1)"                         | 2
            "(10+11)+(1+2+(3+(4-5)+6))+(7+8)" | 47
        }
    }
}

結果

いい感じにわかりやすくかけたかなと。
追加も簡単ですし、みながすすめるのも当然と感じました。

後、テスト失敗時には以下のようにわかりやすく出してくれるのは流石Groovy!

Condition not satisfied:

new Calc().calculation(value) == expected
|          |           |      |  |
|          6           1+2+3  |  7
com.yamap.calc.Calc@bb5566    false

	at com.yamap.calc.CalcTest$括弧なし_正常処理.calculationへの入力値が #value の時は #expected が返される(CalcTest.groovy:54)

気づいたこと

ただ、Eclipseが原因かもしれませんがテスト実行時のJUnitビューにテストケース名が正しく表示されないケースがありました。
本来は「calculationへの入力値が 2*(1+3) の時は 8 が返される」と表示されて欲しいのですが「calculationへの入力値が 2*」で切れてしまいます。
色々試した所「(」があると切れてしまうようです。
テストは正しく実行されるので大きな問題ではありませんが。。。