title: How to deal with iteration/looping in Python behave or BDD Scenarios in general?
body: <p>I am trying to use Python's <a href="https://pythonhosted.org/behave/index.html" rel="nofollow">behave library</a> for writing some BDD/Gherkin style tests on a bunch of delimited textfiles.</p>
  
  <p>A typical scenario would look like this:</p>
  
  <pre><code>Scenario: Check delivery files for illegal values
      Given a file system path to the delivery folder
      When I open each file and read its values
      Then all values in the "foo" column are smaller than 1
      And all values in the "fizz" column are larger than 2
  </code></pre>
  
  <p>Since there are lots of files and each file contains lots of rows, there is no possibility to hardcode all of them into Scenario Outlines. Moreover, I would like to avoid reading whole files into memory at once but rather use generators to iterate over the rows one by one.</p>
  
  <p>I tried the following. However, this is very inefficient on large datasets and large amounts of conditions since each line is read again and again for every <code>then</code> step. Is there any possibility to pass a single row between multiple <code>then</code> steps and start again at the first <code>then</code> step for the next row?</p>
  
  <p>Or is BDD/Gherkin not suited for this kind of testing? What could be an alternative?</p>
  
  <pre><code>import csv
  import itertools
  import os
  
  @given('a file system path to the delivery folder')
  def step(context):
      context.path = '/path/to/delivery/files'
  
  @when('I open each file and read its values')
  def step(context):
  
      file_list = os.listdir(context.path)
  
      def row_generator():
          for path in file_list:
              with open(path, 'rb') as csvfile:
                  reader = csv.reader(csvfile)
                  for row in reader:
                      yield row
  
      context.row_generator = row_generator
  
  # itertools.tee forks off the row generator so it can be used multiple times instead of being exhausted after the first 'then' step
  
  @then('all values in the "foo" column are smaller than 1')
  def step(context):
      for row in itertools.tee(context.row_generator(), 1)[0]:
          assert row['foo'] &lt; 1
  
  @then('all values in the "bar" column are larger than 2')
  def step(context):
      for row in itertools.tee(context.row_generator(), 1)[0]:
          assert row['bar'] &gt; 2
  </code></pre>