Повторне використання огіркових кроків


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. Це насправді потрібно.
Шон Леброн

Відповіді:


102

ОНОВЛЕННЯ : Метод, описаний нижче, застарів. Рекомендований спосіб викликати крок з іншого кроку зараз виглядає так:

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}
вклеїти

1
@BrendanDean Коли цю відповідь було прийнято, stepsметод не існував. Дивіться мою відповідь нижче.
michaeltwofish

Зверніть увагу, що кроки сполучення зараз вважаються антидіаграми, і цього слід уникати. Дивіться вікі- огірок
cucumber.io/docs/guides/anti-patterns/…

103

Зауважте, що метод виклику кроків у межах кроків змінився в останніх версіях огірка, і ви побачите, якщо ви отримаєте помилку типу "ПОПЕРЕДЖЕННЯ: Використання" Дано / Коли / Потім "у визначеннях кроків застаріле, використовуйте" крок ", щоб зателефонуйте замість інших кроків: /path/to/step_definitions/foo_steps.rb: 631: в "блоку в" ". Детальніше дивіться у вікі з огірками .

Суть зміни полягає в тому, що тепер вам слід використовувати методи 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

18
Для чого варто, після більше часу з огірком я рекомендую взагалі не застосовувати кроки. Проблеми важко знайти, і це фактично ускладнює технічне обслуговування. Натомість використовуйте хелперні методи.
michaeltwofish

2
Можливо, ви повинні включити цей коментар у свою відповідь, оскільки він дуже схвалений і все ще отримує голоси. Це допоможе людям помітити цю інформацію
Андрій Боталов

привіт @michaeltwofish, чи можна змінити це в 2017 році? Я отримую syntax error, unexpected tIDENTIFIER, expecting keyword_end stackoverflow.com/questions/43319331 / ...
ericn

43

Виклик кроків із визначення кроків є поганою практикою і має деякі недоліки :

  1. Якщо сценарій не вдасться і є вкладені виклики кроків, ви отримаєте лише останнє визначення кроку, яке викликуєте у сліді стека. Можливо, важко знайти, з якого місця було закликано останній пасинок
  2. Виклик stepdef іноді важче знайти і прочитати, ніж метод рубін
  3. Методи Ruby дають вам більше енергії, ніж виклик кроків із кроків defs

Аслак Геллешей рекомендує витягти популярні дії у Світ, а не повторно використовувати кроки. Це ізолює ці дії в одному місці, полегшує пошук цього коду. Ви можете також витягнути код у звичайні класи або модулі 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

Ось корисна дискусія з цього приводу в листі розсилки огірків - посилання


2
Я вважаю, що цей підхід набагато кращий, ніж викликати функції кроків або кроків з тих самих причин.
пісарук

2
Це має ще одну перевагу. Використовуючи Idea (або Rubymine), ви можете легко перейти до визначень функцій, але не до кроків у кроках% {...}.
слайс

також ця установка відповідає принципу DRY
Sorcerer86pt

2
Хоча я потрапив у проблему повторного використання кроків, я думаю, що це просто погано. Вхід - це лише сума різних кроків: «відвідай щось», «заповни щось». Природним способом було б повторне використання кроків, а не перетворення кожного кроку у виклик функції. IMO, виклик кроків всередині кроків слід просто вдосконалити.
dgmora

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

Використовуйте ключові слова у файлі функцій, що забезпечить повторне використання коду.

Настійно НЕ рекомендується називати ступінь 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
    }
}

Таким чином, існує велика можливість повторного використання коду. Ваші ж «Дані та потім» обробляють і дійсні, і недійсні сценарії. У той же час ваш файл функції має сенс для читачів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.