連載
» 2014年03月25日 18時00分 公開

いまさら聞けないTDD/BDD超入門(2):TDD/BDDの思想とテスティングフレームワークの関係を整理しよう (3/3)

[きょん,STAR(テスト自動化研究会)]
前のページへ 1|2|3       

xSpec

 BDDフレームワークと分類されることが多く、前述のJBehaveからインスパイアされて開発された、Rubyの「RSpec」を始祖とするテスティングフレームワークの総称です。「SpecBDD」と呼ばれることも多く、JBehaveと比較してよりコードの見やすさやドキュメンテーションの作りやすさに注力していることが挙げられます。

 RSpecでは、xUnitでの単語を次のように置き換えています。

  • 「Fixture」→「Context」
  • 「Test」→「Spec」

 RSpecと、Groovy製のBDDフレームワーク「Spock」の簡単な例を次に示します。まずはRSpecです。

describe FizzBuzz do
  [3,99].each do |num|
    it "return 'Fizz' for multiples of 3(#{num})" do
      expect(FizzBuzz.says(num)).to eq("Fizz")
    end
  end
  [5,100].each do |num|
    it "return 'Buzz' for multiples of 5(#{num})" do
      expect(FizzBuzz.says(num)).to eq("Buzz")
    end
  end
  [15,90].each do |num|
    it "return 'FizzBuzz' for multiples of 15(#{num})" do
      expect(FizzBuzz.says(num)).to eq("FizzBuzz")
    end
  end
  [1,98].each do |num|
    it "return number for no multiples of 3 or 5(#{num})" do
      expect(FizzBuzz.says(num)).to eq(num.to_s)
    end
  end
end
RSpec

 次がSpockの例です。

class TDDCycleSpec extends Specification {
    TDDCycle sut
    def "テストを追加してREDにする"() {
        given: "プロジェクトを始める"
        sut = new TDDCycle()
        when: "テストを追加する"
        sut.addTest()
        and:"テストを実行する"
        sut.runTest()
        then: "REDになる"
        sut.status == TDDCycle.RED
    }
    def "REDからプロダクトを追加してGREENにする"() {
        given: "REDになっている"
        sut = new TDDCycle(TDDCycle.RED)
        when: "プロダクトを実装する"
        sut.implement()
        and:"テストを実行する"
        sut.runTest()
        then: "GREENになる"
        sut.status == TDDCycle.GREEN
    }
    def "REDからREFACTORには移れない"() {
        given: "REDになっている"
        sut = new TDDCycle(TDDCycle.RED)
        when: "プロダクトを変更する"
        sut.refactor()
        then: "保証外の手順なので認められない"
        thrown(TDDException)
    }
}
Spock

Cucumber

 BDDフレームワークと分類されることが多く、xUnitやxSpecと異なってJBehaveでもサポートしている「振る舞いを、フォーマットがある自然言語で書くfeatureファイル」と「実際のテスト実行を、プログラミング言語で書くstepファイル」の2つで1つのテストを構成します(実際には、featureファイルとstepファイルの関係はN:Nになりますが割愛します)。

 「Given」「When」「Then」といったBDD由来の語彙を引き継いでいるのはもちろんですが、「Gherkin」というfeatureファイルを書くためのライブラリを導入しているのも特徴です。これによってJBehaveより書きやすくなっています。

 xUnit系のように、さまざまなプログラミング言語でその派生が開発されています。また、Gherkinは37の自然言語が用意されています。もちろん日本語もあります。 日本語ではそれぞれ次のような対応になります。

  • 「Feature」→「フィーチャ」
  • 「Scenario」→「シナリオ」
  • 「Given」→「前提」
  • 「When」→「もし」
  • 「Then」→「ならば」
# language: ja
フィーチャ: TDDのサイクルはRED、GREEN、REFACTORからなっています。
  GREENからREFACTORを飛ばすことはありますが、REDからGREENを飛ばしてREFACTORしないのが特徴です。
  これはテストなどによって保証されている範囲でのみ内部を変更することを「REFACTORING」と呼ぶという定義によるものです。
  シナリオ: プロジェクトを始めるときにTDDの最初の一歩になる手順
    前提 プロジェクトを始めるときはテストがない
    もし 要求を満たすテストを追加する
    かつ テストを実行する
    ならば テストが失敗して、TDDでいう「RED」になる
フィーチャファイル
Given(/^プロジェクトを始めるときはテストがない$/) do
  # 処理
end
When(/^要求を満たすテストを追加する$/) do
  # 処理
end
And(/^テストを実行する$/) do
  # 処理
end
Then(/^テストが失敗して、TDDでいう「RED」になる$/) do
  # 処理
end
ステップファイル

Turnip

 Cucumberは幾つかの技術的なハードルの高さがありました。その1つにfeatureファイルの「Given」「When」「Then」とstepファイルの各メソッドのひも付けが正規表現であることです。注意を払って設計をしなければテストケースが増えたときに対応付けが難しくなったり、正規表現を気にしたfeatureファイルを書くということ自体が難しいと感じる場面もありました。

 これを解決するフレームワークとしてTurnipが開発されました。正規表現によるひも付けを廃止し、またstepファイルは前述のRSpecを使います。それでいて、Cucumberで培われた「Gherkin」を使えるようになっています。

TestDox

 「キャメルケース」で書かれるテストメソッド名を単語に分割して自然言語として読みやすくするテストリポートのサポートツールです。テスト対象クラスを主語にして、テストメソッド名を単語単位に分割した文をつなげることで「自然言語として読めるか」を気にしながらテストを行う事を可能としています。

 統合開発環境「IntelliJ IDEA」のプラグインでもサポートされており、「スネークケース」で書かれているテストメソッド名にも対応しています。

 最近の日本ではあまり聞かないツールであるのは、おそらく「テストメソッド名に日本語を使う」選択肢があるという事情によるものかと思います。英語でテストメソッドを書く場合には、使用を検討するといいでしょう。

JUnit 4の通常の表示
TestDoxの表示

ツールのまとめ

 テスティングフレームワークはxUnitによって大きく前進しました。しかし、TDD初心者がその偉大な習慣を自然と身に付けたり、TDD自体を拡張していくには不足している部分があり、それを補うためのテスティングフレームワークやライブラリが生まれました。

 そのような経緯を踏まえても、xUnitがサポートしている機能が少ないからといってBehaviorを表現できないことはなく、xSpecを使っているからといってBehaviorになっているわけではありません。「どのようなツールを使うと、どのようなコードになりやすいか」という話です。そして、ある問題に対して解決しようとした軌跡が、さまざまなテスティングフレームワーク/ライブラリの系譜であるといえるでしょう。

TDD/BDDの誤解を減らして、次回はBDDの振る舞いを詳細に

 前回にもありますが、TDDは非常に広範であることがうかがえます。思想とツールに分けてTDD/BDDを見ると、広範なTDDの思想を持っている人が使いやすいツール、広範なTDDの思想をより分かりやすくしたり特化させたりする思想、その思想を形式化したツールといったようなイメージになりました。

 テスティングフレームワークはTDDに関する思想の全てを形式知化したものではない(暗黙的な思想が存在する)ですし、用意されているものを使うだけでよいTDDを実践できるわけではありません。そして思想を定着、進化させるために、さまざまなテスティングフレームワークが開発されてきました。

 TDDフレームワークという言葉に特別な意味はないのかもしれませんが、「xUnitってTDDフレームワークだからTDDしかできないんでしょう? モダンな開発はBDDだよ。xSpec使おうよ」のような意見によって誤解が生まれやすくなるのは避けたいところです。

 次回は一体何を書くことがBDDらしく、つまりは振る舞いを書いていることになるのかを、BDDにおける「振る舞い」を捉えることで解説していく予定です。

著者プロフィール

きょん

ソフトウェアテストアーキテクト。ソフトウェアテストを専門にし、テスト戦略やテスト設計に関するモデリングの手法やアジャイルなソフトウェアテストに関する研究と実践を行っています。GroovyやF#などのプログラミング言語を好んでいて、断然IntelliJ IDEA派です。Nagoya.Testing、SCMBootCamp、基礎勉強会などの勉強会を主催しています。


前のページへ 1|2|3       

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。