104 votes

Réutiliser les étapes de concombre

Je veux réutiliser une partie de concombre étapes mais n'arrive pas à trouver le bon chemin.

Je veux écrire une étape comme:

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

Mais alors une autre étape comme:

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

Afin de tester l'authentification de l'utilisateur, je peux utiliser l'ancien, mais la plupart des autres endroits, je peux utiliser ce dernier, et pas de repro code.

Est-il possible d'appeler cette autre étape, ou dois-je simplement mettre de la logique dans une méthode d'assistance, et de l'appel dit de la méthode de chaque tâche (essentiellement d'une méthode d'extraction de refactoring, qui, après la lecture de ma question qui me fait croire que c'est effectivement la meilleure façon de toute façon)?

103voto

michaeltwofish Points 2378

Notez que la méthode pour appeler les étapes dans les étapes a changé dans les versions récentes de concombre, qui vous le verrez si vous obtenez une erreur comme "AVERTISSEMENT: l'Utilisation de" Données/Quand/Puis "à l'étape définitions est obsolète, utiliser "étape" pour appeler d'autres étapes à la place:/chemin/vers/step_definitions/foo_steps.rb:631:dans le `bloc ' ". Voir le concombre wiki pour plus de détails.

L'essentiel de ce changement est que vous devez désormais utiliser l' step ou steps méthodes.

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

101voto

tomafro Points 3852

Vous pouvez appeler des étapes à partir d’autres étapes comme celle-ci:

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

Si tous les scénarios d'une fonctionnalité nécessitent cette opération (ou d'autres étapes), vous pouvez également ajouter un arrière-plan à chaque fonctionnalité, avec les étapes courantes, comme suit:

 Background:
  Given I log in with valid credentials

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

UPDATE : La méthode décrite ci-dessus est obsolète. La méthode recommandée pour appeler une étape à partir d'une autre étape ressemble maintenant à ceci:

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

43voto

Andrey Botalov Points 6566

Appel étapes de définitions est une mauvaise pratique qui a quelques inconvénients:

  1. Si le scénario va échouer et y sont imbriqués l'étape invocations, vous obtenez seulement la dernière invoqué l'étape de définition de la trace de la pile. Il peut être difficile de trouver d'où cette dernière stepdef a été appelé
  2. Appel à stepdef est parfois plus difficile de trouver et de lire que la méthode ruby
  3. Ruby méthodes vous donnent plus de puissance que d'appeler les étapes à partir de l'étape defs

Aslak Hellesøy recommande d'extraire populaire actions Monde au lieu de réutiliser les étapes. Il isole ces actions en un seul lieu, rend ce code plus facile à trouver.

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

Voici une discussion utile sur le sujet dans le Concombre liste de diffusion - lien

9voto

Rimian Points 7805

Mieux vaut envelopper vos pas entre% {} plutôt que entre guillemets. Ensuite, vous n'avez pas besoin d'échapper aux guillemets que vous devrez utiliser fréquemment .:

 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
 

1voto

LINGS Points 352

Réutilisez les mots-clés dans le fichier de fonctions pour permettre la réutilisation du code.

Il n'est PAS vivement recommandé d'appeler les paramètres de pas dans les paramètres de pas.

J'écrirais mon fichier de fonctionnalité de cette façon,

 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       |
 

Dans ma définition de l'étape, (c'est 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
    }
}
 

De cette manière, il y a beaucoup de possibilité de réutilisation du code. Your same Given and Then gère les scénarios valides et non valides. Dans le même temps, votre fichier de fonctions a du sens pour les lecteurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X