pythonparameterspytestparameter-passingfixtures

How to pass a parameter to a fixture function in Pytest?


I am using py.test to test some DLL code wrapped in a python class MyTester. For validating purpose I need to log some test data during the tests and do more processing afterwards. As I have many test_... files I want to reuse the tester object creation (instance of MyTester) for most of my tests.

As the tester object is the one which got the references to the DLL's variables and functions I need to pass a list of the DLL's variables to the tester object for each of the test files (variables to be logged are the same for a test_... file). The content of the list is used to log the specified data.

My idea is to do it somehow like this:

import pytest

class MyTester():
    def __init__(self, arg = ["var0", "var1"]):
        self.arg = arg
        # self.use_arg_to_init_logging_part()

    def dothis(self):
        print "this"

    def dothat(self):
        print "that"

# located in conftest.py (because other test will reuse it)

@pytest.fixture()
def tester(request):
    """ create tester object """
    # how to use the list below for arg?
    _tester = MyTester()
    return _tester

# located in test_...py

# @pytest.mark.usefixtures("tester") 
class TestIt():

    # def __init__(self):
    #     self.args_for_tester = ["var1", "var2"]
    #     # how to pass this list to the tester fixture?

    def test_tc1(self, tester):
       tester.dothis()
       assert 0 # for demo purpose

    def test_tc2(self, tester):
       tester.dothat()
       assert 0 # for demo purpose

Is it possible to achieve it like this or is there even a more elegant way?

Usually I could do it for each test method with some kind of setup function (xUnit-style). But I want to gain some kind of reuse. Does anyone know if this is possible with fixtures at all?

I know I can do something like this: (from the docs)

@pytest.fixture(scope="module", params=["merlinux.eu", "mail.python.org"])

But I need to the parametrization directly in the test module. Is it possible to access the params attribute of the fixture from the test module?


Solution

  • This is actually supported natively in py.test via indirect parametrization.

    In your case, you would have:

    @pytest.fixture
    def tester(request):
        """Create tester object"""
        return MyTester(request.param)
    
    
    class TestIt:
        @pytest.mark.parametrize('tester', [['var1', 'var2']], indirect=True)
        def test_tc1(self, tester):
           tester.dothis()
           assert 1