読者です 読者をやめる 読者になる 読者になる

デシジョンテーブルとSpockで試すTDD(ネタ)

TDD Groovy

※この記事はメモ書きです
※この記事には突っ込みどころ満載のコードが含まれています。つまりそういうことです。

  • (1/22修正)コードを一部修正

デシジョンテーブルとSpockを使ってTDDするとどうなるかということを、FizzBuzzで試してみましょう。

用意するもの

デシジョンテーブルをつくる

CEGTestを使って原因結果グラフを書きましょう。するとデシジョンテーブルは同時に自動生成されているはずです。


デシジョンテーブルをそのままSpockに移植してみる

デシジョンテーブルがそのまま使えるなら、GroovyわからないとかSpockしらないという言い訳はできませんよね?

import spock.lang.Specification
import spock.lang.Ignore

class FizzBuzzTest extends Specification {

    @Ignore
    def "与えられた数値によって指定のFizzBuzz文字列を返す" () {

        where:
        三の倍数         << [ true  , false ,  true  , false ]
        五の倍数         << [ false , true  ,  true  , false ]
        Fizzを返す       << [ true  , false ,  false , false ]
        Buzzを返す       << [ false , true  ,  false , false ]
        FizzBuzzを返す   << [ false , false ,  true  , false ]
        値を文字列で返す << [ false , false ,  false , true  ]
    }      
}

whereはParameterized Testを記述するために使うのですが…むむ、こう書いてみるとデシジョンテーブルそのままですね。
でもTDDするときには邪魔だなーと思わなくもないので

れっつTDD

あとでかく

Ignoreをはずしてテストが動くようにする

デシジョンテーブルを利用したテストコードも実行できるように手直しします。
ちなみに、今回はTDD時に書いたテストコードは捨てることにしました。

import spock.lang.Specification

class FizzBuzzTest extends Specification {

    def "与えられた数値によって指定のFizzBuzz文字列を返す" () {

        setup:
        def otherNum = 2
        def num = {if(三の倍数 && 五の倍数) 15 else if(三の倍数) 3 else if(五の倍数) 5 else otherNum}.call()
        def result = {if (Fizzを返す) 'Fizz' else if(Buzzを返す) 'Buzz' else if(FizzBuzzを返す) 'FizzBuzz' else otherNum.toString()}.call()

        expect:
        sayFizzBuzz(num) == result

        // この書き方もOK。こう書いた方が見やすいよね!
        where:
        三の倍数 | 五の倍数 | Fizzを返す | Buzzを返す | FizzBuzzを返す | 値を文字列で返す
        true     | false    | true       | false      | false          | false
        false    | true     | false      | true       | false          | false
        true     | true     | false      | false      | true           | false
        false    | false    | false      | false      | false          | true
    }

    def sayFizzBuzz(def num) {
       if(num % 15 == 0) 'FizzBuzz'
       else if(num % 3 == 0) 'Fizz'
       else if(num % 5 == 0) 'Buzz'
       else num.toString()
    }      
}

テスト実行…はい、通りました。

なにがおいしいの?

CEGTestで原因結果グラフを書けばデシジョンテーブルが、そして(ジェネレートツール自作すれば)デシジョンテーブルからSpockコードが一部自動生成できるというロマンが成り立ちます。

以上、誰得記事でした。