py.test: Get expected values for test functions for different fixtures from configuration

StackOverflow https://stackoverflow.com//questions/24022616

  •  21-12-2019
  •  | 
  •  

Question

I want to setup tests using py.test using two (or more) fixtures for different levels in my project. For each fixture i want to execute different test functions which shall get the expected values by parameters depending on the fixture used for the test.

This is what i want to do:

def getGroups(boardstr, xlen, ylen):
    board = Board(boardstr, xlen, ylen)
    groups = MyClass.findGroups(board.get_field())
    return groups

@pytest.fixture(scope='module')
def groups_3():
    # ... setup for level 3
    return getGroups(boardstr, xlen, ylen)

@pytest.fixture(scope='module')
def groups_10():
    # ... setup for level 10
    return getGroups(boardstr, xlen, ylen)

# this is my test data, which i want to use
expected_values = {
    "groups_3": {
        "test_total_groups": 9,
        "test_total_clickable_groups": 5,
        "test_total_colors": 3
    },
    "groups_10": {
        "test_total_groups": 22,
        "test_total_clickable_groups": 7,
        "test_total_colors": 3
    },
}

# "groups" shall be the fixture for the following test functions
# and the test methods shall be executed with groups_3 and groups_10 as fixture
def test_total_groups(groups, expected):
    assert len(groups) == expected

def test_total_clickable_groups(groups, expected):
    assert len([grp for grp in groups if grp.clickable is True]) == expected

def test_total_colors(groups, expected):
    assert len(np.unique([grp.color for grp in groups])) == expected

is there a way to achive this using py.test? Is this possible by using the parametrization feature?

I tried some variants like:

@pytest.mark.parametrize("groups, expected", [
        (groups_3(), 5),
        (groups_10(), 7),
    ])
def test_total_clickable_groups(groups, expected):
    assert len([grp for grp in groups if grp.clickable is True]) == expected

but i didnt succeed.

Was it helpful?

Solution

Perhaps it is useful for somebody. I found a way to do it (inspired by holgerkrekel.net/2009/05/13/parametrizing-python-tests-generalized/):

def getGroups(boardstr, xlen, ylen):
    board = Board(boardstr, xlen, ylen)
    groups = MyClass.findGroups(board.get_field())
    return groups

def groups_3():
    # ... setup for level 3
    return getGroups(boardstr, xlen, ylen)

def groups_10():
    # ... setup for level 10
    return getGroups(boardstr, xlen, ylen)

# decorator function
def params(funcarglist):
    def wrapper(function):
        function.funcarglist = funcarglist
        return function
    return wrapper

def pytest_generate_tests(metafunc):
    # called once per each test function
    for funcargs in getattr(metafunc.function, 'funcarglist', ()):
        # schedule a new test function run with applied **funcargs
        metafunc.addcall(funcargs=funcargs)

class TestClass:

    groups_3 = groups_3()
    groups_10 = groups_10()

    @params([dict(g=groups_3, e=9),
             dict(g=groups_10, e=22)])
    def test_total_groups(self, g, e):
        assert len(g) == e


    @params([dict(g=groups_3, e=5),
             dict(g=groups_10, e=7)])
    def test_total_clickable_groups(self, g, e):
        assert len([grp for grp in g if grp.clickable is True]) == e


    @params([dict(g=groups_3, e=3),
             dict(g=groups_10, e=3)])
    def test_total_colors(self, g, e):
        assert len(np.unique([grp.color for grp in g])) == e
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top