キュウリのステップを再利用する


103

いくつかのキュウリの手順を再利用したいのですが、正しい方法が見つからないようです。

次のようなステップを記述したいと思います。

Given /^I login with (.*) credentials$/ |type|
  # do stuff with type being one of "invalid" or "valid"
end

しかし、次のような別のステップがあります:

Given /^I login successfully$
  # call "Given I login with valid credentials"
end

したがって、ユーザー認証のテストでは前者を使用できますが、他のほとんどの場所では後者を使用でき、実際にコードを再現する必要はありません。

その別のステップを呼び出す方法はありますか、またはヘルパーメソッドにロジックを配置し、各タスクから上記のメソッドを呼び出しますか(基本的にメソッド抽出リファクタリング、私の質問を読んだ後、それが実際に最良の方法であると確信させます)とにかく)?


1
誰かが混乱しているdo場合のために、ここの誰もがdo...end、Rubyステップ定義でブロックを開始するために必要なものを省いています。実際には必須です。
Shaun

回答:


102

UPDATE:以下で説明するメソッドは廃止されました。別のステップ内からステップを呼び出すための推奨される方法は、次のようになります。

Given /^I login successfully$/
    step "I login with valid credentials" 
end 

古い、非推奨のメソッド(参照用):

次のような他のステップからステップを呼び出すことができます。

Given /^I login successfully$/
  Given "I login with valid credentials"
  Then "I should be logged in"
end

機能内のすべてのシナリオでこれ(または他の手順)が必要な場合は、次のように、共通の手順を使用して各機能に背景を追加することもできます。

Background:
  Given I log in with valid credentials

Scenario: Change my password
  Given I am on the account page

5
さらに簡単そうのようにガーキンコードを貼り付けている:steps %Q{Given I am logged in}
BrendanDean

1
@BrendanDeanこの回答が受け入れられたとき、stepsメソッドは存在しませんでした。以下の私の答えを参照してください。
michaeltwofish

現在、結合ステップはアンチパターンと見なされており、回避する必要があります。キュウリのwikiを参照してください- cucumber.io/docs/guides/anti-patterns/...
月Molak

103

最近のバージョンのcucumberでは、ステップ内でステップを呼び出す方法が変更されていることに注意してください。「WARNING:Using 'Given / When / Then' is using deprecated、use to step to to代わりに他のステップを呼び出します:/path/to/step_definitions/foo_steps.rb:631:in `block in '"。詳細はキュウリのwikiをご覧ください。

変更の要点は、stepor stepsメソッドを使用する必要があることです。

When /^I make all my stuff shiny$/
  step "I polish my first thing"
end

When /^I make all my stuff shiny$/
  steps %Q{
    When I polish my first thing
    When I shine my second thing
  }
end

18
それだけの価値があるので、Cucumberをしばらく使った後は、ステップ内のステップをまったく使用しないことをお勧めします。問題を追跡するのは難しく、実際にはメンテナンスが難しくなります。代わりに、ヘルパーメソッドを使用してください。
michaeltwofish

2
たぶん、このコメントは非常に賛成であり、それでも投票を受け取るので、回答に含める必要があります。それは人々がこの情報に気づくのに役立ちます
Andrei Botalov

こんにちは@ michaeltwofish、2017年にこれに変更はありますか?syntax error, unexpected tIDENTIFIER, expecting keyword_end stackoverflow.com/questions/43319331/…を
ericn

43

ステップ定義からステップを呼び出すことは悪い習慣であり、いくつかの欠点があります:

  1. シナリオが失敗し、ネストされたステップ呼び出しがある場合、スタックトレースで最後に呼び出されたステップ定義のみが取得されます。最後のstepdefが呼び出された場所を見つけるのは難しいかもしれません
  2. stepdefの呼び出しは、rubyメソッドよりも見つけて読むのが難しい場合があります
  3. Rubyメソッドは、ステップ定義からステップを呼び出すよりも強力です

AslakHellesøy 、ステップを再利用する代わりに、人気のアクションをWorldに抽出すること推奨しています。これらのアクションを1つの場所に分離し、このコードを見つけやすくします。通常のRubyクラスまたはモジュールにコードを抽出することもできます。

#/support/world_extensions.rb
module KnowsUser
  def login
    visit('/login')
    fill_in('User name', with: user.name)
    fill_in('Password', with: user.password)
    click_button('Log in')
  end

  def user
    @user ||= User.create!(:name => 'Aslak', :password => 'xyz')
  end
end
World(KnowsUser)

#/step_definitions/authentication_steps.rb
When /^I login$/ do
  login
end

Given /^a logged in user$/ do
  login
end

ここでは、Cucumberメーリングリストのトピックに関する役立つディスカッションがあります- リンク


2
このアプローチは、上記と同じ理由で、step関数またはsteps関数を呼び出すよりもはるかに優れていると思います。
pisaruk

2
これには別の利点があります。Idea(またはRubymine)を使用すると、関数定義に簡単にジャンプできますが、ステップ%{...}のステップにはジャンプできません。
スリップセット

また、このセットアップはDRY原則に従います
Sorcerer86pt 2013年

2
ステップの再利用という問題にぶつかりましたが、これはただ悪いことだと思います。ログインは、「何かを訪れる」、「何かを埋める」という異なるステップの合計です。自然な方法は、各ステップを関数の呼び出しに変換するのではなく、ステップを再利用することです。IMO、ステップ内のステップの呼び出しは改善されるべきです。
dgmora 2013年

9

ステップは引用符ではなく%{}で囲みます。次に、頻繁に使用する必要がある二重引用符をエスケープする必要はありません。

Given /^I login successfully$
  step %{I login with valid credentials}
end

Given /^I login with (.*) credentials$/ |type|
  # do stuff with type being one of "invalid" or "valid"
end

5
これは答えではなくコメントでした。
ケルビン

1

コードの再利用性を提供する機能ファイルでキーワードを再利用します。

ステップ定義内でステップ定義を呼び出すことは強く推奨されていません。

このようにして機能ファイルを書きます

Scenario Outline: To check login functionality
    Given I login with "<username>" and "<password>"
    Then I "<may or may not>" login successfully

Examples:
    |username|password|may or may not|
    |paul    |123$    |may           |
    |dave    |1111    |may not       |

私のステップ定義では、(これはJavaです)

@Given(I login with \"([^\"]*)\" and \"([^\"]*)\"$)
public void I_login_with_and(String username, String password){

   //login with username and password

}

@Then(I \"([^\"]*)\" login successfully$)
public void I_login_successully_if(String validity){

    if(validity.equals("may")){
        //assert for valid login
    }
    else
    if(validity.equals("may not")){
        //assert for invalid login
    }
}

このようにして、多くのコードの再利用性があります。同じGiven and Thenが有効なシナリオと無効なシナリオの両方を処理します。同時に、読者にとって機能ファイルは理にかなっています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.