Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Monday, July 4, 2016

Reuse Cucumber steps

Reuse Cucumber steps


I want to reuse some Cucumber steps but can't seem to find the right way.

I want to write a step like:

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

But then have another step like:

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

So in testing user authentication I can use the former, but most other places, I can use the latter, and not actually have to repro code.

Is there a way to call that other step, or do I just put the logic in a helper method, and call said method from each task (basically a method extraction refactoring, which, after reading my question makes me believe that's actually the best way anyway)?

Answer by tomafro for Reuse Cucumber steps


UPDATE: The method described below has been deprecated. The recommended way to call a step from within another step now looks like this:

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

Old, deprecated method (for reference):

You can call steps from other steps like this:

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

If all of the scenarios within a feature require this (or other steps), you can also add a Background to each features, with the common steps, like so:

Background:    Given I log in with valid credentials    Scenario: Change my password    Given I am on the account page  

Answer by michaeltwofish for Reuse Cucumber steps


Note that the method for calling steps within steps has changed in recent versions of cucumber, which you'll see if you get an error like "WARNING: Using 'Given/When/Then' in step definitions is deprecated, use 'step' to call other steps instead:/path/to/step_definitions/foo_steps.rb:631:in `block in ' ". See the cucumber wiki for details.

The gist of the change is that you should now use the step or steps methods.

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  

Answer by Rimian for Reuse Cucumber steps


Best wrap your steps in %{} rather than quotes. Then, you don't need to escape double quotes which you'll need to use frequently.:

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  

Answer by Andrei Botalov for Reuse Cucumber steps


Calling steps from step definitions is a bad practice and has some disadvantages:

  1. If scenario will fail and there are nested step invocations, you will get only the last invoked step definition in the stack trace. It may be hard to find from which place that last stepdef was called
  2. Call to stepdef is sometimes harder to find and read than ruby method
  3. Ruby methods give you more power than calling steps from step defs

Aslak Helles?y recommends to extract popular actions to World instead of reusing steps. It isolates those actions in one place, makes this code easier to find.

#/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  

Here is a useful discussion on the subject in Cucumber mailing list - link

Answer by LINGS for Reuse Cucumber steps


Reuse keywords in feature file which will provide code reusability.

It is highly NOT recommended to call step defs within step defs.

I would write my feature file this way,

Scenario Outline: To check login functionality      Given I login with "" and ""      Then I "" login successfully    Examples:      |username|password|may or may not|      |paul    |123$    |may           |      |dave    |1111    |may not       |  

In my step definition, (This is 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      }  }  

In this way, there is a lot of code reusability. Your same Given and Then handles both valid and invalid scenarios. At the same time, your feature file makes sense to the readers.


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.