Turnip README 超意訳


受け入れテストのフレームワークである Turnip のざっくりとした利用方法を掴むために超意訳してみました。参考までに、関連する記事も貼っておきます。

* [jnicklas/turnip](https://github.com/jnicklas/turnip)
* [Rubyist Magazine - エンドツーエンドテストの自動化は Cucumber から Turnip へ](http://magazine.rubyist.net/?0042-FromCucumberToTurnip#l20)
* [Turnip](http://www.slideshare.net/rs_wisteria/turnip)
* ["turnip" - 記事一覧 - Thanks Driven Life](http://gongo.hatenablog.com/archive/category/turnip)
* [Rspec/Capybara/Turnipの入門記事を全力でまとめてみた - 酒と泪とRubyとRailsと](http://morizyun.github.io/blog/the-rspec-book-review-rails/)

***

# Turnip

Turnip は、RSpec の為の [Gherkin](https://github.com/cucumber/cucumber/wiki/Gherkin) 拡張です。RSpec 環境にて、Gherkin でテストを記述して実行することが可能です。基本的には、RSpec で Cucumber フィーチャを記述することが可能です。

## インストール

gem をインストールします。

```
gem install turnip
```

もしくは、Gemfile に追記して `bundle` を実行します。

``` ruby:Gemfile
group :test do
  gem "turnip"
end
```

プロジェクトルートディレクトリに `.rspec` ファイルを用意して、以下の行を追記します。

```ruby:.rspec
-r turnip/rspec
```

## 互換性

Turnip は、Ruby 1.8.X では動作しません。

## 利用方法

`spec` ディレクトリの任意の場所に、フィーチャファイルを作成します。

```cucumber:spec/acceptance/attack_monster.feature
Feature: Attacking a monster
  Background:
    Given there is a monster

  Scenario: attack the monster
    When I attack it
    Then it should die
```

他の RSpec のスペックファイルを実行するように、フィーチャを実行することが可能です。

```
rspec spec/acceptance/attack_monster.feature
```

`rake spec` や `rspec spec` にて全てのスペックを実行した場合、フィーチャも自動的に実行されます。

## ステップ定義

任意のモジュール上に、ステップを定義することが可能です。

```ruby
module MonsterSteps
  step "there is a monster" do
    @monster = Monster.new
  end
end
```

RSpec にて、このモジュールをインクルードすることが可能です。

```ruby
RSpec.configure { |c| c.include MonsterSteps }
```

### グローバルなステップ定義

Turnip は、RSpec に自動的にインクルードする為に `Turnip::Steps` と呼ばれる特別なモジュールを持っています。このモジュールをステップ定義に追加することで、全てのフィーチャで利用可能なステップ定義になります。その為の便利なショートカットを用意しています。以下のように、グローバルなネームスペースにて、`step` を呼ぶだけです。

```ruby
step "there is a monster" do
  @monster = Monster.new
end
```

### プレースホルダ

Cucumber と違って、Turnip はステップ定義の正規表現をサポートしていないことに注意して下さい。但し、以下のように、ステップ定義でプレースホルダを利用することが可能です。

```ruby
step "there is a monster called :name" do |name|
  @monster = Monster.new(name)
end
```

ダブルクォート、または、何も付けない状態でこのプレースホルダに値を置くことが可能です。

```cucumber
Given there is a monster called Jonas
And there is a monster called "Jonas Nicklas"
```

また、以下のように、別の単語や単語の任意の部分を指定することも可能です。

```ruby
step "there is/are :count monster(s)" do |count|
  @monsters = Array.new(count) { Monster.new }
end
```

この場合、"there is X monster" か "there are X monsters" の両方に合致します。

### ステップ定義のスコープ

ステップ定義はモジュール上に定義されている為、任意の機能を利用することが可能です。ステップ定義の数が膨大になったり、潜在的な重複をさせたくない場合、非常に役に立ちます。

データベースと直接やり取りをしたり、ユーザーインタフェースを介するような幾つかのシナリオを持っている場合、以下のように、組み込むことが可能です。

```ruby
module InterfaceSteps
  step "I do it" do
    ...
  end
end

module DatabaseSteps
  step "I do it" do
    ...
  end
end

RSpec.configure do |config|
  config.include InterfaceSteps, :interface => true
  config.include DatabaseSteps, :database => true
end
```

Turnip は、RSpec のメタデータにタグを付与するので、それらのシナリオに適切にタグ付けするために、RSpec の条件付きの場合のみ、それらのステップ定義が含まれるように利用することが可能です。

つまり、同名のステップ定義であっても、フィーチャファイルで利用することが可能です。

```cucumber
@interface
Scenario: do it through the interface

@database
Scenario: do it through the database
```

この例では、`@interface` と `@database` の両方の機能をタグ付けするわけではないことに注意してください。

このパターンは非常に一般的なため、便利なショートカットが用意されています。

``` ruby
steps_for :interface do
  step "I do it" do
    ...
  end
end
```

詳しくは、[features/alignment_steps.rb](https://github.com/jnicklas/turnip/blob/master/examples/steps/alignment_steps.rb) を参照してください。

### ステップ定義ファイルの場所

Turnip は自動的に `spec_helper` ファイルを読み込みます。そこから、任意の場所、任意のステップを置いて、好きなようにそれらをロードすることが可能です。例えば、`spec/steps` にステップ定義ファイルを格納している場合、以下のようにロードするこことが可能です。

``` ruby
Dir.glob("spec/steps/**/*steps.rb") { |f| load f, true }
```

`spec_helper` をロードする前に、Turnip の設定ファイルである `turnip_helper` と呼ばれるファイルをロードしようとします。

他のテストを実行した時にロードする必要が無いように、このファイルからステップ定義をロードする方が有益かもしれません。

### ステップ定義からステップ定義を呼ぶ

ステップ定義は Ruby のメソッドのように呼び出すことが可能です。しかし、ステップ定義の名称には恐らくスペースやその他の特殊文字が含まれているため、ステップを呼び出すために `send` を利用する必要があります。

``` ruby
step "the value is :num" do |num|
  @value = num
end

step "the value is twice as much as :num" do |num|
  send "the value is :num", num * 2
end
```

時には、`step` を利用することもあるでしょう。

``` ruby
step "the value is :num" do |num|
  @value = num
end

step "the value is the magic number" do
  step "the value is 3"
end
```

### メソッドによるステップ定義

ステップ定義として、既存のメソッドを利用することが可能です。このステップ定義は、Turnip フィーチャにて利用することが可能です。

``` ruby
module MonsterSteps
  def create_monster(name)
    @monster = Monster.new(:name => name)
  end
  step :create_monster, "there is a monster called :name"
end
```

## カスタムステッププレースホルダ

Turnip は、カスタムプレースホルダをサポートしています。

``` ruby
step "there are :count monsters" do |count|
  count.times { Monster.new(name) }
end

placeholder :count do
  match /\d+/ do |count|
    count.to_i
  end

  match /no/ do
    0
  end
end
```

これで、以下のように、これらのステップ定義を使用することが可能です。

``` cucumber
Given there are 4 monsters
Given there are no monsters
```

これで、正規表現の一致を抽出することが可能です。

``` ruby
placeholder :monster do
  match /(blue|green|red) (furry|bald) monster/ do |color, hair|
    Monster.new(color, hair)
  end
end
```

## テーブルによるステップ定義

Turnip は Cucumber に似たパラメータとして、テーブル定義のステップをサポートしています。

```cucumber
Scenario: This is a feature with a table
  Given there are the following monsters:
    | Name    | Hitpoints |
    | Blaaarg | 23        |
    | Moorg   | 12        |
  Then "Blaaarg" should have 23 hitpoints
  And "Moorg" should have 12 hitpoints
```

テーブルは、Cucumber の `Cucumber::Ast::Table` オブジェクトとほとんど同じような動作をする `Turnip::Table` オブジェクトです。

例えば、ハッシュの配列は `Turnip::Table` によって変換されます。

```ruby
step "there are the following monsters:" do |table|
  @monsters = {}
  table.hashes.each do |hash|
    @monsters[hash['Name']] = hash['Hitpoints'].to_i
  end
end
```

## Capybara と一緒に使う方法

`spec_helper` にて `turnip/capybara` を require してください。`@javascript` や `@selenium` のような Cucumber で利用されるタグを同じように利用することが可能です。Turnip フィーチャは `:type => :feature` メタデータと一緒に実行されます。