2009-05-27 19 views
94

Quiero reutilizar algunos pasos de Pepino pero parece que no puedo encontrar el camino correcto.Reutilizar Pasos de pepino

Quiero escribir un paso como:

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

Pero luego tener otro paso como:

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

Así que en la autenticación de usuario de prueba que se puede utilizar la primera, pero la mayoría de otros lugares, puede usar este último y no tener que reprogramar.

Hay una manera de llamar a ese otro paso, o simplemente pongo la lógica en un método auxiliar, y llamo a dicho método desde cada tarea (básicamente una refactorización de extracción de métodos, que después de leer mi pregunta me hace creer que de hecho la mejor manera de todos modos)?

+1

En caso de que alguien esté confundido, todos aquí están dejando de lado el 'do' requerido para iniciar el bloque' do ... end' en la definición del paso de Ruby. De hecho es obligatorio. –

Respuesta

98

ACTUALIZACIÓN: El método descrito a continuación ha quedado obsoleto. El método recomendado para llamar a un paso desde el interior de otro paso ahora se ve así:

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

Viejo, método obsoleto (para referencia):

Puede llamar a pasos de otras medidas como esta :

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

Si todos los escenarios dentro de una característica requieren este (u otras medidas), también puede agregar un fondo a cada uno características, con e e pasos comunes, así:

Background: 
    Given I log in with valid credentials 

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

Aún más fácil es pegar el código de pepinillo de la siguiente manera: 'pasos% Q {Dado que estoy conectado}' – BrendanDean

+1

@BrendanDean Cuando se aceptó esta respuesta, el método 'steps' no existía. Ver mi respuesta a continuación. – michaeltwofish

+6

de esta manera ha quedado obsoleto – Karan

101

Tenga en cuenta que el método para llamar pasos dentro pasos ha cambiado en las últimas versiones de pepino, que verá si se obtiene un error como "ADVERTENCIA: El uso de 'Dada/Cuando/Entonces 'en las definiciones de paso está en desuso, use' step 'para llamar a otros pasos: /path/to/step_definitions/foo_steps.rb: 631: en' block in ' ". Vea el cucumber wiki para más detalles.

La esencia del cambio es que ahora debe utilizar los métodos step o 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 
+16

Por lo que vale la pena, después de más tiempo con Pepino, recomiendo no utilizar los pasos en pasos. Los problemas son difíciles de rastrear y realmente dificulta el mantenimiento. En cambio, use métodos de ayuda. – michaeltwofish

+1

Tal vez, debe incluir este comentario en su respuesta, ya que está muy modificado y aún recibe votos. Ayudará a las personas a notar esta información –

+0

hi @michaeltwofish, ¿hay algún cambio en esto en 2017? Estoy obteniendo 'error de sintaxis, inesperado tIDENTIFIER, esperando keyword_end' http://stackoverflow.com/questions/43319331/calabash-android-high-level-step-definition-syntax-error-unexpected-tidentifi – ericn

8

Mejor ajuste sus pasos en% {} en lugar de comillas. Entonces, no es necesario para escapar comillas dobles que se necesita para utilizar con frecuencia .:

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

Esto debería haber sido un comentario en lugar de una respuesta. – Kelvin

40

Calling pasos de definiciones paso es una mala práctica y tiene some disadvantages:

  1. Si escenario fallan y hay invocaciones de pasos anidados, obtendrá solo la última definición de paso invocado en el seguimiento de la pila.Puede ser difícil de encontrar en qué lugar la última stepdef fue llamado
  2. llamada a stepdef a veces es difícil de encontrar y leer que el método de rubí
  3. métodos de Ruby le dan más poder que llamar a pasos de defs paso

Aslak Hellesøy recommends para extraer acciones populares al World en lugar de reutilizar los pasos. Aísla esas acciones en un solo lugar, hace que este código sea más fácil de encontrar. También puede extraer el código a las clases o módulos de Ruby habituales.

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

Aquí está una discusión útil sobre el tema en la lista de correo Pepino - link

+2

Creo que este enfoque es mucho mejor que llamar a las funciones de pasos o pasos por las mismas razones antes mencionadas. – pisaruk

+2

Esto tiene otro beneficio. Usando Idea (o Rubymine), puede pasar fácilmente a las definiciones de funciones, pero no a los pasos en los pasos% {...}. – slipset

+0

también esta configuración sigue el principio DRY – Sorcerer86pt

1

palabras clave reutilización en función de archivo que proporcionará la reutilización del código.

NO se recomienda llamar a las definiciones de pasos dentro de los pasos definidos.

me gustaría escribir mi archivo característica de esta manera,

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  | 

En mi definición de paso, (Esto es 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 esta manera, hay una gran cantidad de reutilización de código. Lo mismo dado y luego maneja escenarios válidos y no válidos. Al mismo tiempo, su archivo de características tiene sentido para los lectores.

Cuestiones relacionadas