title: Generating py.test tests in Python
body: <p>Question first, then an explanation if you're interested.</p>
  <p>In the context of py.test, how do I generate a large set of test functions from a small set of test-function templates?</p>
  <p>Something like:</p>
  <pre class="lang-py prettyprint-override"><code>models = [model1,model2,model3]
  data_sets = [data1,data2,data3]
  
  def generate_test_learn_parameter_function(model,data):
      def this_test(model,data):
          param = model.learn_parameters(data)
          assert((param - model.param) &lt; 0.1 )
      return this_test
  
  for model,data in zip(models,data_sets):
      # how can py.test can see the results of this function?
      generate_test_learn_parameter_function(model,data)
  </code></pre>
  <p>Explanation:</p>
  <p>The code I'm writing takes a model structure, some data, and learns the parameters of the model. So my unit testing consists of a bunch of model structures and pre-generated data sets, and then a set of about 5 machine learning tasks to complete on each structure+data.</p>
  <p>So if I hand code this I need one test per model per task. Every time I come up with a new model I need to then copy and paste the 5 tasks, changing which pickled structure+data I'm pointing at. This feels like bad practice to me. Ideally what I'd like is 5 template functions that define each of my 5 tasks and then to just spit out test functions for a list of structures that I specify.</p>
  <p>Googling about brings me to either a) factories or b) closures, both of which addle my brain and suggest to me that there must be an easier way, as this problem must be faced regularly by proper programmers. So is there?</p>
  <hr />
  <p>EDIT: So here's how to solve this problem!</p>
  <pre class="lang-py prettyprint-override"><code>def pytest_generate_tests(metafunc):
      if &quot;model&quot; in metafunc.funcargnames:
          models = [model1,model2,model3]
          for model in models:
              metafunc.addcall(funcargs=dict(model=model))
  
  def test_awesome(model):
      assert model == &quot;awesome&quot;
  </code></pre>
  <p>This will apply the <code>test_awesome</code> test to each model in my list of models! Thanks @dfichter!</p>
  <p>(NOTE: that assert always passes, btw)</p>