社内の勉強会でなんかしゃべれーってことになり。なんとなくSpockがどっかで気になってたので、SpockどころかGroovyすら触ったことほぼないですけど、ドキュメントをサラーっと読んで面白いなーと思うところをSpock Web Consoleで動かしつつ紹介してみたりしました!復習がてらもういちど読んでみまする。
https://code.google.com/p/spock/wiki/SpockBasics
全体はこんな感じかな。読みやすいね。
class MyFirstSpecificationextends Specification {def"pushing an element on the stack"() { setup:def stack =new Stack()def elem ="push me" when: stack.push(elem) then: !stack.empty stack.size() ==1 stack.peek() == elem }}
これをWebConsoleで実行してみるテスト!
MyFirstSpecification - pushing an element on the stack
失敗するようにしてみると。
stack.size() ==2
こうなる
MyFirstSpecification - pushing an element on the stack FAILED Condition not satisfied: stack.size() == 2 | | | | 1 false [push me] at MyFirstSpecification.pushing an element on the stack(Script1.groovy:12)
キャーステキー!!!
てことで説明を読んでみる。
6つのブロックがある。
準備するとこ
setup:def stack =new Stack()def elem ="push me"
when: と then: はセットで使われる。when: でテストしたいことを実行して、then: でチェック。
then: のところはassertion使わなくても、bool値になってればいいみたいね。読み易いや。
when:stack.push(elem)then:!stack.emptystack.size() ==1stack.peek() == elem
thrown()メソッドが使えると。
when:stack.pop()then:thrown(EmptyStackException)stack.empty
例外の内容をチェックしたい場合はこんなふうにできる。
when:stack.pop()then:def e = thrown(EmptyStackException)e.cause ==null
もちょっと違う書き方だとこんな感じ。こっちのが型がはっきりしてるからIDEにやさしいよって。それと、前から読む感じになるので、読みやすいよって。僕もこっちのがなんとなく好きだな。
when:stack.pop()then:EmptyStackException e = thrown()e.cause ==null
例外が投げられなかったことのチェックはこんな感じ
def"HashMap accepts null key"() { setup:def map =new HashMap() when: map.put(null,"elem") then: notThrown(NullPointerException)}
モックを使ったテストなんかも書けるよーって。詳細はhttp://docs.spockframework.org/en/latest/interaction_based_testing.html かな。
def"events are published to all subscribers"() {def subscriber1 = Mock(Subscriber)def subscriber2 = Mock(Subscriber)def publisher =new Publisher() publisher.add(subscriber1) publisher.add(subscriber2) when: publisher.fire("event") then:1 * subscriber1.receive("event")1 * subscriber2.receive("event")}
publisher.fire("event")を呼び出したら、1回だけsubscriber1.receive("event")が実行されるよってことみたいね。
mockとかspyとかありそうなので、また今度チェックしてみよっと。
実行してチェックを1行で書いたほうが自然なときはwhen:とthen:じゃなくて、expected:が使えるよーって。例えばこういう場合は
when:def x = Math.max(1,2)then:x ==2
expected:使って一行で書くほうが分かり良いよね
expect:Math.max(1,2) ==2
後処理すね
setup:def file =new File("/some/path")file.createNewFile()// ...cleanup:file.delete()
例外が投げられてもここは実行されるとのこと。いいなー。
パラメタライズドテストで使うっぽいすね。これいいすね。さらっとhttp://docs.spockframework.org/en/latest/data_driven_testing.html を読んでみた。
例えばこういうテストをしたいとき
class MathSpecextends Specification {def"maximum of two numbers"() { expect:// exercise math method for a few different inputs Math.max(1,3) ==3 Math.max(7,4) ==7 Math.max(0,0) ==0 }}
こう書けるす。
class Mathextends Specification {def"maximum of two numbers"(int a,int b,int c) { expect: Math.max(a, b) == c where: a | b | c1 |3 |37 |4 |40 |0 |0 }}
読みやすくて素敵すなー。さらに、メソッドの引数は where:で分かるとのことで書かなくてもよいと。それと入力値と期待値の間はもう一個パイプを増やした方が分かり良いやろーって。こうなる
class DataDrivenextends Specification {def"maximum of two numbers"() { expect: Math.max(a, b) == c where: a | b || c3 |5 ||57 |0 ||70 |0 ||0 } }
ちょっとのことだけど。そゆとこ気を遣ってるのいいねー。
実行結果がどういう風に出力されるかってのを見たいので、失敗するようにしてみよう。
class DataDrivenextends Specification {def"maximum of two numbers"() { expect: Math.max(a, b) == c where: a | b || c3 |5 ||57 |0 ||50 |0 ||0 } }
んで、WebConsoleで実行!
DataDriven - maximum of two numbers FAILED Condition not satisfied: Math.max(a, b) == c | | | | | 7 7 0 | 5 false at DataDriven.maximum of two numbers(Script1.groovy:4)
ふむふむ。ところで @Unroll というアノテーションをつけるとパラメータ毎に展開してくれるっぽい。やってみよう。
class DataDrivenextends Specification { @Unrolldef"maximum of two numbers"() { expect: Math.max(a, b) == c where: a | b || c3 |5 ||57 |0 ||50 |0 ||0 } }
結果はこうなった。なる。
DataDriven - maximum of two numbers[0] - maximum of two numbers[1] FAILED Condition not satisfied: Math.max(a, b) == c | | | | | 7 7 0 | 5 false at DataDriven.maximum of two numbers(Script1.groovy:5) - maximum of two numbers[2]
でも、パラメータの値をメソッド名に展開してくれる仕組みがなかったっけ?と思ってたら次に書いてあったわ。
class DataDrivenextends Specification { @Unrolldef"maximum of #a and #b is #c"() { expect: Math.max(a, b) == c where: a | b || c3 |5 ||57 |0 ||50 |0 ||0 } }
実行ー!
DataDriven - maximum of 3 and 5 is 5 - maximum of 7 and 0 is 5 FAILED Condition not satisfied: Math.max(a, b) == c | | | | | 7 7 0 | 5 false at DataDriven.maximum of #a and #b is #c(Script1.groovy:5) - maximum of 0 and 0 is 0
そうそう、これこれ。分かりやすいね。
ドキュメントとしての仕様か。
setup:"空の銀行口座を用意して"// ...when:"100円振り込むと"// ...then:"残高が100円になる"// ...
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。