Search code examples
pythonbddpython-behave

How to use behave context.table with key value table?


I saw that it is possible to access data from context.table from Behave when the table described in the BDD has a header. for example:

Scenario: Add new Expense
  Given the user fill out the required fields
    | item | name  | amount |
    | Wine | Julie | 30.00  |

To access this code it's simply:

for row in context.table:
  context.page.fill_item(row['item'])
  context.page.fill_name(row['name'])
  context.page.fill_amount(row['amount'])

That works well and it's very clean, however, I have to refactor code when I have a huge amount of lines of input data. for example:

Given I am on registration page
When I fill "test@test.com" for email address
And I fill "test" for password
And I fill "Didier" for first name 
And I fill "Dubois" for last name
And I fill "946132795" for phone number
And I fill "456456456" for mobile phon
And I fill "Company name" for company name
And I fill "Avenue Victor Hugo 1" for address
And I fill "97123" for postal code
And I fill "Lyon" for city
And I select "France" country
...
15 more lines for filling the form

How could I use the following table in behave:

|first name | didier |
|last name  | Dubois |
|phone| 4564564564   |
So on ...

How would my step definition look like?


Solution

  • To use a vertical table rather than a horizontal table, you need to process each row as its own field. The table still needs a header row:

    When I fill in the registration form with:
        | Field      | Value  |
        | first name | Didier |
        | last name  | Dubois |
        | country    | France |
        | ...        | ...    |
    

    In your step definition, loop over the table rows and call a method on your selenium page model:

    for row in context.table
      context.page.fill_field(row['Field'], row['Value'])
    

    The Selenium page model method needs to do something based on the field name:

    def fill_field(self, field, value)
      if field == 'first name':
        self.first_name.send_keys(value)
      elif field == 'last name':
        self.last_name.send_keys(value)
      elif field == 'country':
        # should be instance of SelectElement
        self.country.select_by_text(value)
      elif
        ...
      else:
        raise NameError(f'Field {field} is not valid')