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.