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

cucumberのめも

ruby

最近までcucumberを使ってたのでその時に気づいたことのメモです。

基本通りfeatures以下にfeatureファイルとかを置いていたとして、cucumberはfeature以下のファイルを全て読み込むようなのでステップの定義がユニークじゃないと意図しないほうが呼ばれてしまうので気をつけないといけないのですね。
そのかわり同じステップを使いたい場合は重複して実装する必要は無いということになるのですが…
あと、@マーク付きのインスタンス変数も同じような感じなので注意ですね。
例えばこんなディレクトリ構造にして

 features ---  background
          |    |--- background.rb
          |--  say_goodbye
          |    |--- say_goodbye.feature
          |    |--- say_goodbye.rb
          |--  say_hello
          |    |--- say_hello.feature
          |    |--- say_hello.rb

say_hello.featureをこのようにしてバックグラウンド、シナリオのアウトライン、シナリオを定義します。

Feature: cucumber test say_hello

  In order to foobar
  As a Foo
  I want test say_hello

Background: This is a common background
  Given I start a test I setup global data
    |greeting|
    |hello, world|

  Scenario Outline: say_hello scenario outline
    Given a test scenario
    When I print "<message>" to user
    Then this test will finish

  Scenarios: say_hello scenario 1
    |message|
    |foobar|

say_hello.rbを以下の用にしてBackgroundは別ファイルに記述してみます。

Given /^a test scenario$/ do
  printf "\\nshow greeting\\n"
  printf "%s\\n", @greeting
end

When /^I print "(.*?)" to user$/ do |message|
  printf "%s\\n", message
end

Then /^this test will finish$/ do
  printf "this test will finish\\n"
end

background.rbはこんな感じです、greetingに.featureで定義したテーブルから読んだ値を入れるようにします。

Given /^I start a test I setup global data$/ do |table|
  @greeting = table.raw[1][0]
end

あとはsay_goodbye.featureですが、こちらはバックグラウンドはデータが違うだけにして、シナリオのステップも最後以外は同じにします。

@say_goodbye

Feature: cucumber test say_goodbye

  In order to foobar
  As a Bar
  I want test say_goodbye

Background: This is a common background
  Given I start a test I setup global data
    |greeting|
    |goodbye, world|

  Scenario Outline: say_goodbye scenario outline
    Given a test scenario
    When I print "<message>" to user
    Then I want to say goodbye again

  Scenarios: say_goodbye scenario 1
    |message|
    |FOOBAR|

say_goodbye.rbは最終ステップだけ書きます。

Then /^I want to say goodbye again$/ do
  printf "%s\\n", @greeting
end

これでfeaturesがあるディレクトリに移動して以下のように実行すると

$ cucumber --tags @say_hello
  1. background.rbにあるステップを実行
  2. say_hello.rbのステップを実行

↑という風に動くので↓のような出力になります。

[masami@saga:~/cc]$ cucumber --tags @say_hello
@say_hello
Feature: cucumber test say_hello

  In order to foobar
  As a Foo
  I want test say_hello

  Background: This is a common background    # features/say_hello/say_hello.feature:9
    Given I start a test I setup global data # features/background/background.rb:1
      | greeting     |
      | hello, world |

  Scenario Outline: say_hello scenario outline # features/say_hello/say_hello.feature:14
    Given a test scenario                      # features/say_hello/say_hello.rb:1
    When I print "<message>" to user           # features/say_hello/say_hello.rb:6
    Then this test will finish                 # features/say_hello/say_hello.rb:10

    Scenarios: say_hello scenario 1
      | message |
      |
show greeting
hello, world
foobar
this test will finish
 foobar  |

1 scenario (1 passed)
4 steps (4 passed)
0m0.005s

say_goodbyeも同じような感じでbackground.rbのステップ、say_helloのステップ、say_goodbyeのステップが実行されます。

[masami@saga:~/cc]$ cucumber --tags @say_goodbye
@say_goodbye
Feature: cucumber test say_goodbye

  In order to foobar
  As a Bar
  I want test say_goodbye

  Background: This is a common background    # features/say_goodbye/say_goodbye.feature:9
    Given I start a test I setup global data # features/background/background.rb:1
      | greeting       |
      | goodbye, world |

  Scenario Outline: say_goodbye scenario outline # features/say_goodbye/say_goodbye.feature:14
    Given a test scenario                        # features/say_hello/say_hello.rb:1
    When I print "<message>" to user             # features/say_hello/say_hello.rb:6
    Then I want to say goodbye again             # features/say_goodbye/say_goodbye.rb:1

    Scenarios: say_goodbye scenario 1
      | message |
      |
show greeting
goodbye, world
FOOBAR
goodbye, world
 FOOBAR  |

1 scenario (1 passed)
4 steps (4 passed)
0m0.005s

と言うわけでcucumberを使うときにステップ名が重複した場合、意図しないステップが実行される可能性があるので気をつけないといけないですねφ(・・*)ゞ ウーン