Повторное использование шагов огурца

Я хочу повторно использовать несколько шагов Cucumber, но не могу найти правильный путь.

Я хочу написать такой шаг:

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

ОБНОВЛЕНИЕ. Метод, описанный ниже, устарел. Рекомендуемый способ вызова шага с другого шага теперь выглядит следующим образом:

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

Ответ 2

Обратите внимание, что метод для вызова шагов в шагах изменился в последних версиях огурца, и вы увидите, если вы получите сообщение об ошибке "ПРЕДУПРЕЖДЕНИЕ: использование" Given/When/Then "в определениях шагов устарело, используйте команду step для вместо этого вызовите другие шаги: /path/to/step_definitions/foo_steps.rb: 631: in 'block in' ". Подробности смотрите в вики огурца.

Суть изменения заключается в том, что теперь вы должны использовать методы step или 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

Ответ 3

Вызов шагов из определений шагов - это плохая практика и некоторые недостатки:

  • Если сценарий завершится с ошибкой и будут введены вложенные шаги, в трассировке стека вы получите только последнее вызванное определение шага. Может быть, трудно найти, с какого места, которое последний шаг был назван
  • Вызов на stepdef иногда сложнее найти и прочитать, чем метод ruby.
  • Рубиновые методы дают вам больше возможностей, чем вызов шагов с шага defs

Aslak Hellesøy рекомендует извлекать популярные действия для World вместо повторного использования шагов. Он изолирует эти действия в одном месте, облегчает поиск кода. Вы также можете извлечь код для обычных классов или модулей 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 - ссылка

Ответ 4

Лучше всего обернуть ваши шаги в% {}, а не кавычки. Затем вам не нужно избегать двойных кавычек, которые вам нужно использовать часто.:

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

Повторное использование ключевых слов в файле функций, которые будут обеспечивать повторное использование кода.

НЕ рекомендуется называть step defs в шагах defs.

Я бы написал свой файл функций таким образом,

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
    }
}

Таким образом, существует много повторного использования кода. То же самое задано и затем обрабатывает как допустимые, так и недействительные сценарии. В то же время ваш файловый файл имеет смысл для читателей.