calling steps from step definitions¶
Our tests should be as expressive as possible. However, we also want to re-use steps that we’ve seen before. With the tools we’ve used so far, you could end up with seriously long step definitions.
Scenario: Logged-in user does something cool.
Given I go to the home page
And I click the login button
And I fill in username:floppy password:banana
And I click "Login"
When I finally do something interesting
Then I'm already too bored to care.
In this case, we probably had a test case (maybe several) for which it was actually valuable to express how the user interacted with the login form. That’s where we got the step definitions for our login sequence. When the login form isn’t especially interesting any more, however, these steps are just noise. We’d really like to be able to define something like this without duplicating our step definitions.
Scenario: Logged-in user does something cool.
Given I am logged in
When I do something interesting
Then The world becomes a better place
Lettuce affords you the ability to write such a “step of steps” with a set of helpers matching each of the grammar terms Given, When and Then. You could accomplish the above like so.
@step('I am logged in')
def is_logged_in(step):
step.given('I go to the home page')
step.given('I click the login button')
# ... and so on.
running blocks of steps¶
It is sometimes even desirable to run blocks of steps, copy-and-pasted directly from Feature specifications. The Step.behave_as method lets you do this, and you can use str.format to fill in parameters dynamically. For example, we can write the above step definition like so:
@step('I am logged in')
def is_logged_in(step):
step.behave_as("""
Given I go to the home page
And I click the login button
And I fill in username:{user} password:{pass}
And I click "Login"
""".format(user='floppy', pass='banana'))
This can be combined with step argument capture for step definitions that are both expressive and DRY.