TDD in Action

ペアでTDDしつづけるイベントです。
一緒にペア組んでいただいた方にめちゃイロイロ教えていただきました。ちょうラッキーというヤツです!

# 今日のブツをgithubにupしてみました。
https://github.com/zuisener/tddact/tree/master/src/tddact

簡単なまとめ

Quick JUnit

会場ついてから「そうそう、Quick JUnit使おう」と思って急遽入れました。

テストとプロダクションコードを一発で切り替えたりできます。
TDDだとテストとプロダクションコードを行ったり来たりするので便利です。

  • Ctrl + 9: テスティングペアを切り替える
  • Ctrl + 0: テスト実行

(最初ショートカット忘れてて困ったけどペアの方に教えてもらった)
このテスティングペアの切替機能はクラス名の命名で決まります。デフォルトで<クラス名>と<クラス名>Testを切り替えます。(このルールは設定で変えられる)

ただし今回はWindows on Macの変態環境だったためかわかりませんが、Ctrl + 0が動かず毎回マウス使ってメニューから選択していました(´・ω・`)

あ、ちなみに最初無名パッケージで開発していたのですが、パッケージがないと切り替えできないようです。適当なパッケージに移動したら使えるようになりました。

JUnit4

そこそこテストが増えると見づらくなってきたのでテストをまとめることに。
JUnit4はほとんど使ったことがなかったのですがテストスイートを分けずにstaticなネストクラスごとにまとめることができるようです。

  • @RunWith(Enclosed.class) をテストクラスにつけると、そのクラスのstaticなネストクラスごとにテストが実行される

実行がどうの、というより、これをやるとEclipseエディタ上でネストクラス内にテストメソッドをまとめられます。するとエディタ上ではネストクラスを折りたたみ表示できるのでとても見やすい。

JUnit4は@Test @Before @Afterくらいしか押さえてなかったけれど@RunWithのオプションは便利なようです。

他にも@Theoriesと@Datapointsとか。

いま調べてみるとJUnit4のアノテーションではパラメタライズドテストもサポートされているようです。

でも今回パラメタライズドテストは後述する別の方法で試しました。

Spock

ライブTDDでGroovyのテストフレームワークSpockが面白そうだったのでそれを使ってJavaコードをテストすることに。
いままでJava/JUnitで作ったテストをまずGroovyで実行しました。

Groovy:Unexpected problem with AST transform: The Spock compiler plugin cannot execute because Spock 0.6.0-groovy-1.8 is not compatible with Groovy 2.0.0. For more information, see http://versioninfo.spockframework.org     VendingMachineTest.groovy     /VendingMachine/src/tddact     行 0     Java 問題
org.codehaus.groovy,2.0.0.xx-20120703-1400-e37-RELEASE,plugins/org.codehaus.groovy_2.0.0.xx-20120703-1400-e37-RELEASE/,4,false
  • 設定が終わるとgroovyのコードでテストが書けるし、動くようになる。
    • もしかするとビルドパスの構成で追加したGroovyライブラリを一旦除去して追加し直す必要があるかも
    @Test
    public void 十円玉() {
        v.insert(10);
        assert 10 == v.getAvailableTotalAmount() // この行がassertEqualsメソッドをgroovyの記法に一部変えてみたところ
    }

    @Test
    public void 五十円玉() {
        v.insert(50);
        assertEquals(50, v.getAvailableTotalAmount());

    }
  • うごいたので今度はテストメソッドまるごとSpockっぽく書きなおして見ることに。
    def "投入したお金と合計金額"() {
        expect:
            v.insert(amount)
            v.getAvailableTotalAmount() == totalAmount
        where:
            amount | totalAmount
            10     | 10
            50     | 50
            100    | 100
            1000   | 1000
    }

このwhere句の書き方で表形式っぽく見える部分がすごいわかりやすい!(※ 等幅フォントに限る)
各行のパラメータでそれぞれexpectが実行されるようになってます。パラメタライズドテストわかりやすい。

ただしJUnitのテストメソッド1つだけをdef形式?で書いて動かしてもこの部分はスルーされてしまいます。
というのもSpockで動かすにはテストクラスがSpecificationクラスを継承している必要がある。
ということで新規にgroovyテストクラスを作成し、ちょっとずつ移植。無事SpockでJavaコードがテストできました!

こーんなかんじにパラメータに可変長なものを使いたい時はリストを入れたりもできる

    def "複数回お金を投入する改"() {
        expect:
            for(i in amount) {
                v.insert(i)
            }
            v.getAvailableTotalAmount() == totalAmount
        where:
            amount        | totalAmount
            [10]          | 10
            [10, 50]      | 60
            [10, 50, 100] | 160
    }

パラメータにオブジェクトを使いたい時はShared変数という物を使う。
ちなみに@Sharedを使うときは手動でimport文(import spock.lang.Shared)を書く。Eclipseが自動訂正してくれないので…
(というかgroovyソース全般的に補完が弱い。メソッド名補完できないとか)
単にJava/JUnitでのフィールド変数というだけな気がする...

    @Shared juice1 = new Juice("コーラ"    , 150, 5)
    @Shared Juice juice2 = new Juice("レッドブル", 260, 0)
    @Shared Juice juice3 = new Juice("レッドブル", 500, 10)

    def "ジュースの在庫情報を得られる改"() {
        expect:
            Set<Juice> juiceStock =  v.getJuiceStock()
            juiceStock.containsAll(juiceList as Set)
            dummy == 1
        where:
            juiceList          | dummy
            [juice1]           | 1
            [juice2]           | 1
            [juice1, juice2]   | 1
    }

ちなみにEclipseのGroovy対応がいまいちなのか型チェック無しのバージョンでやっているからか不明だがQuick JUnitは使えないのでテスティングペアの切り替えは手動で面倒。
Spockはパラメタライズドはわかりやすくかけて便利だけどそれ以外のメリットあまりないかも…。
ただしSpock(というかGroovy?)のおかげのPower Assertの機能が便利すぎる。

    @Test
    public void 十円玉() {
        v.insert(10);
        assert 11 == v.getAvailableTotalAmount() // わざと期待値を間違えて書いている
    }

Power Assertによって以下がビューに表示される

Assertion failed:

assert 11 == v.getAvailableTotalAmount()
          |  | |
          |  | 10
          |  tddact.VendingMachine@1814dd0
          false

※ いまいち綺麗に表示されてませんがフォント(CSS?)のせいです。Eclipseでもコンソールフォントを等幅のものにするときれいにどの変数・式がどういう内容なのかわかりやすく表示されます。

いままでワンライナーで書いてたりすると、その行がしくっていてもどの部分式が死んでるのかよくわからないのでデバッガで逐次実行して状態を確かめたりとか死にたくなる感じでしたが、それが一発でわかる!超便利!
帰り際に参加者のかたとこの辺を話していたのですが、Spock+PowerAssertで新しく使うライブラリのAPIを学習するのに自分で適当なパラメータを入れて、戻り値を予想して、それを突き合わせる、とかいう学習テストをするときに便利とのことです。おお、すばらしい。

その他

TDDは以上なのですが、ライブコーディング中に気になった他人のエディタなど。

勉強になったこと

  • TDDやるまえにドメイン洗い出すのは確かに。忘れがち。テストする品質も。
  • 世の中には多言語をふつーに語れるすごい人がいっぱいいる
  • Specs2 DIS

知らないEclipseショートカット

  • aEで補完するとassertEqualsが補完
  • エディタ上でAltを押しながら上下矢印すると選択行が移動

おやつなど。

  • なぜか朝10時から提供されたビール
  • ラクルさんの無限コーヒー
  • ハッピーターン
  • すごくおいしいおやつ


ということで名前はしってたけど使ってなかったものや新しいものを知れて非常に良かった2日間でした。
主催者のみなさまナイスな機会を与えていただきありがとうございます。
すばらしい会場提供していただいたニフティさん、日本オラクルさんありがとうございました。