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

Java での BDD(振舞駆動開発)その2 - easyb

前回 id:fits:20080202 は、Java 開発への BDD(Behavior Driven Development, 振舞駆動開発)適用という事で JDave と RspecJRuby で実行)を簡単に使ってみたが、今回は Groovy で振る舞いを記述する easyb を試してみた。

easyb の特徴は以下の通り。

  • Groovy で記述
  • 振る舞いの記法に Behavior DSL と Story DSL の 2種類を用意
    • Behavior DSL は before、it で振る舞いを定義(Rspec 風)
    • Story DSL は given、when、then を使ってストーリーを定義
  • コマンドライン、Ant、Maven で実行可能

とりあえず、以下のような環境で簡単なサンプルを書いて実行してみた。

  • Groovy 1.5.4
  • easyb 0.7
  • Gant 1.1.1

Behavior DSL を使って振る舞いを定義

Behavior DSL を使う場合は、Rspec と同様に before に初期化処理、it に期待する振る舞いを定義する。ファイル名は Behavior で終わる事が推奨されている。

dataBehavior.groovy ファイル
import sample.Data

before "Data の初期化", {
    data = new Data("test")
}

it "名前を持っている", {
    data.getName().shouldBe "test"
}

it "名前は変更できない", {
    ensureThrows(Exception) {
        data.setName("aaa")
    }
}

Story DSL を使ってストーリー形式で振る舞いを定義

Story DSL を使う場合は、given に初期化処理、when で振る舞い、then に期待する結果を定義する。ファイル名は Story で終わる事が推奨されている。

dataStory.groovy ファイル
import sample.Data

scenario "名前を持っている", {
    given "Data の初期化", {
        data = new Data("test")
    }

    then "コンストラクタで設定された値が名前となるべき", {
        data.getName().shouldBe "test"
    }
}

scenario "名前は変更できない", {
    given "Data の初期化", {
        data = new Data("test")
    }

    when "名前を変更する", {
        setname = {
            data.setName("aaa")
        }
    }

    then "例外が発生すべき", {
        ensureThrows(Exception) {
            setname()
        }
    }
}

実行

ビルドファイルも Groovy で記述したかったので、今回は Gant を使って実行してみた。

build.gant ファイル
srcDir = "src"
destDir = "dest"
specDir = "spec"

target("default": null) {

    path(id: "project.classpath") {
        pathelement(path: "$destDir")

        fileset(dir: "c:/easyb-0.7") {
            include(name: "**/*.jar")
        }
    }

    //easyb タスクの定義
    taskdef(name: "easyb", classname: "org.disco.easyb.ant.SpecificationRunnerTask") {
        classpath(refid: "project.classpath")
    }

    mkdir(dir: "$destDir")

    //Java ソースファイルのコンパイル
    javac(srcdir: "$srcDir", destdir: "$destDir") {
        classpath(refid: "project.classpath")
    }

    //easyb の実行
    easyb {
        classpath(refid: "project.classpath")
        behaviors(dir: "$specDir") {
            include(name: "**/*.groovy")
        }
    }
}

target("clean": null) {
    delete(dir: "$destDir")
}
実行結果
>gant
    [easyb] easyb is preparing to process 2 file(s)
    [easyb] 10 behavior steps run successfully
    [easyb] easyb execution passed

結論

簡単に使ってみた限りでは、Rspec もいいがこっちもありかなと思う。特に Java の開発に使うなら Groovy を使う方が便利かも。
easyb on Grails なんかもあるといいな。