Gurkenschritte wiederverwenden

103

Ich möchte einige Gurkenschritte wiederverwenden, kann aber nicht den richtigen Weg finden.

Ich möchte einen Schritt schreiben wie:

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

Aber dann noch einen Schritt wie:

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

Beim Testen der Benutzerauthentifizierung kann ich die erstere verwenden, aber an den meisten anderen Stellen kann ich die letztere verwenden und muss den Code nicht wirklich neu programmieren.

Gibt es eine Möglichkeit, diesen anderen Schritt aufzurufen, oder füge ich die Logik einfach in eine Hilfsmethode ein und rufe diese Methode von jeder Aufgabe aus auf (im Grunde genommen ein Refactoring der Methodenextraktion, das mich nach dem Lesen meiner Frage glauben lässt, dass dies tatsächlich der beste Weg ist wie auch immer)?

Daniel Huckstep
quelle
1
Falls jemand verwirrt ist, lässt jeder hier das doErforderliche aus, um den do...endBlock in der Ruby-Schrittdefinition zu starten . Es ist in der Tat erforderlich.
Shaun Lebron

Antworten:

102

UPDATE : Die unten beschriebene Methode ist veraltet. Die empfohlene Methode zum Aufrufen eines Schritts aus einem anderen Schritt sieht nun folgendermaßen aus:

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

Alte, veraltete Methode (als Referenz):

Sie können Schritte aus anderen Schritten wie diesem aufrufen:

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

Wenn alle Szenarien innerhalb eines Features dies (oder andere Schritte) erfordern, können Sie jedem Feature auch einen Hintergrund hinzufügen, mit den folgenden allgemeinen Schritten:

Background:
  Given I log in with valid credentials

Scenario: Change my password
  Given I am on the account page
Tomafro
quelle
5
Noch einfacher ist es, den steps %Q{Given I am logged in}
Gurkencode
1
@BrendanDean Als diese Antwort akzeptiert wurde, existierte die stepsMethode nicht. Siehe meine Antwort unten.
michaeltwofish
Bitte beachten Sie, dass Konjunktionsschritte jetzt als Anti-Muster betrachtet werden und vermieden werden sollten. Siehe das Gurken-Wiki - cucumber.io/docs/guides/anti-patterns/…
Jan Molak
103

Beachten Sie, dass sich die Methode zum Aufrufen von Schritten innerhalb von Schritten in den letzten Versionen von Gurke geändert hat. Wenn ein Fehler wie "WARNUNG: Die Verwendung von" Gegeben / Wann / Dann "in Schrittdefinitionen ist veraltet, verwenden Sie" Schritt "bis Rufen Sie stattdessen andere Schritte auf: /path/to/step_definitions/foo_steps.rb: 631: in `block in '". Weitere Informationen finden Sie im Gurken-Wiki .

Der Kern der Änderung ist, dass Sie jetzt die Methoden stepoder stepsverwenden sollten.

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
michaeltwofish
quelle
18
Nach mehr Zeit mit Cucumber empfehle ich, keine Schritte innerhalb von Schritten zu verwenden. Probleme sind schwer zu finden und erschweren die Wartung. Verwenden Sie stattdessen Hilfsmethoden.
Michaeltwofish
2
Vielleicht sollten Sie diesen Kommentar in Ihre Antwort aufnehmen, da er sehr positiv bewertet ist und dennoch Stimmen erhält. Es wird den Menschen helfen, diese Informationen zu bemerken
Andrei Botalov
hi @michaeltwofish, gibt es 2017 eine Änderung daran? Ich bekomme syntax error, unexpected tIDENTIFIER, expecting keyword_end stackoverflow.com/questions/43319331/…
ericn
43

Das Aufrufen von Schritten aus Schrittdefinitionen ist eine schlechte Praxis und hat einige Nachteile :

  1. Wenn das Szenario fehlschlägt und verschachtelte Schrittaufrufe vorhanden sind, wird nur die zuletzt aufgerufene Schrittdefinition in der Stapelverfolgung angezeigt. Es kann schwierig sein zu finden, von welchem ​​Ort aus der letzte stepdef aufgerufen wurde
  2. Der Aufruf von stepdef ist manchmal schwieriger zu finden und zu lesen als die Ruby-Methode
  3. Ruby-Methoden bieten Ihnen mehr Leistung als das Aufrufen von Schritten aus Schrittdefinitionen

Aslak Hellesøy empfiehlt , beliebte Aktionen in World zu extrahieren, anstatt Schritte wiederzuverwenden . Es isoliert diese Aktionen an einem Ort und erleichtert das Auffinden dieses Codes. Sie können Code auch in übliche Ruby-Klassen oder -Module extrahieren.

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

Hier ist eine nützliche Diskussion zu diesem Thema in der Gurken-Mailingliste - Link

Andrei Botalov
quelle
2
Ich glaube, dieser Ansatz ist aus den oben genannten Gründen viel besser als das Aufrufen von step- oder step-Funktionen.
Pisaruk
2
Dies hat einen weiteren Vorteil. Mit Idea (oder Rubymine) können Sie leicht zu Funktionsdefinitionen springen, jedoch nicht zu den Schritten in den Schritten% {...}.
Slipset
Auch dieses Setup folgt dem DRY-Prinzip
Sorcerer86pt
2
Obwohl ich auf das Problem der Wiederverwendung von Schritten gestoßen bin, finde ich das einfach schlecht. Login ist nur die Summe der verschiedenen Schritte: "etwas besuchen", "etwas füllen". Der natürliche Weg wäre, Schritte wiederzuverwenden, anstatt jeden Schritt in einen Aufruf einer Funktion umzuwandeln. IMO, das Aufrufen von Schritten innerhalb von Schritten sollte nur verbessert werden.
Dgmora
9

Schließen Sie Ihre Schritte am besten in% {} und nicht in Anführungszeichen ein. Dann müssen Sie sich doppelten Anführungszeichen nicht entziehen, die Sie häufig verwenden müssen:

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
Rimian
quelle
5
Dies hätte ein Kommentar statt einer Antwort sein sollen.
Kelvin
1

Verwenden Sie Schlüsselwörter in der Feature-Datei erneut, um die Wiederverwendbarkeit des Codes zu gewährleisten.

Es wird NICHT empfohlen, Step-Defs innerhalb von Step-Defs aufzurufen.

Ich würde meine Feature-Datei so schreiben,

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       |

In meiner Schrittdefinition (Dies ist 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
    }
}

Auf diese Weise gibt es viel Wiederverwendbarkeit von Code. Das gleiche Given and Then behandelt sowohl gültige als auch ungültige Szenarien. Gleichzeitig macht Ihre Feature-Datei für die Leser Sinn.

LINGS
quelle