K
K
kicherov_maxim2022-04-01 15:04:18
Python
kicherov_maxim, 2022-04-01 15:04:18

How to use fixtures in test parameterization?

Good afternoon, I have a test and I would like to run it parameterized.

fixtures

@fixture
def contractor(contractor_data: t.Dict[str, t.Any]) -> Contractor:
    return Contractor.from_json(**contractor_data)


@fixture
def contractor_data() -> t.Dict[str, t.Any]:
    return {
        'pk': '62287058f8428cb7e5520536',
        'name': 'ООО Тестовый поставщик',
        'inn': '7802853013',
        'ogrn': '1147847079313',
        'director': 'director',
        'address': 'г.Тюмень улю Ленина 1',
        'email': '[email protected]',
        'created': datetime(2022, 3, 24, 10, 3, 38, 554000),
        'updated': datetime(2022, 3, 24, 10, 3, 38, 554000),
        'deleted': False
    }


@fixture
def bank(bank_data: t.Dict[str, t.Any]) -> Bank:
    return Bank.from_json(**bank_data)


@fixture
def bank_data() -> t.Dict[str, t.Any]:
    return {
        'pk': '622870bff8428cb7e5520537',
        'name': 'ЗАПАДНО-СИБИРСКОЕ ОТДЕЛЕНИЕ№8647 ПАО СБЕРБАНК',
        'bic': '047102651',
        'swift': 'SABRRUMMTN1',
        'inn': '7707083893',
        'kpp': '720302020',
        'okpo': '09171401',
        'address': '625023, Тюменская обл, г Тюмень, ул Рижская, д 61',
        'created': datetime(2022, 3, 24, 10, 3, 38, 554000),
        'updated': datetime(2022, 3, 24, 10, 3, 38, 554000),
        'deleted': False
    }


test without parameterization works
@mark.asyncio
async def test_broker(bank):
    BanksControl.objects = AsyncMock(return_value=[bank])
    with patch.multiple(Bank, save=AsyncMock(return_value=bank)):
        with patch.multiple(SyncRpc, __init__=MagicMock(return_value=None), send=MagicMock(return_value=None)):
            actor = GetModels(ACTORS.SYNC_BANK_BROKER, control=BanksControl)
            await actor()
            BanksControl.objects.assert_awaited_once_with(state=True)
            actor.rpc.send.assert_called_once_with(bank)
            assert_that(actor.queued, equal_to(1))


failed parametrization attempt
@mark.asyncio
@mark.parametrize('control, model, document', [(BanksControl, Bank, bank)])
async def test_broker(control, model, document):
    control.objects = AsyncMock(return_value=[document])
    with patch.multiple(model, save=AsyncMock(return_value=document)):
        with patch.multiple(SyncRpc, __init__=MagicMock(return_value=None), send=MagicMock(return_value=None)):
            actor = GetModels(ACTORS.SYNC_BANK_BROKER, control=BanksControl)
            await actor()
            BanksControl.objects.assert_awaited_once_with(state=True)
            actor.rpc.send.assert_called_once_with(document)
            assert_that(actor.queued, equal_to(1))

firstly, the decorator does not see the fixture, I have to add from tests.fixtures import bank, although it is declared in conftest, and when I passed it to the test in the working first example, everything worked fine. Second, I get the error
AttributeError: 'function' object has no attribute.

Still I try like this
@mark.parametrize('control, model, document', [(BanksControl, Bank, bank())])

And got Fixture "bank" called directly. Fixtures are not meant to be called directly, but are created automatically when test functions request them as parameters.

Can you please tell me how to run the test with different parameters?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Mikhail Krostelev, 2022-04-01
@kicherov_maxim

You need to pass the name of the fixture in the parameters, and pull it out in the test via request
Here is an example

# conftest.py

@pytest.fixture
def a_fixture():
    return 'a'

@pytest.fixture
def b_fixture():
    return 'b'

# модуль с тестами

@mark.parametrize('data_param, expected', [('a_fixture', 'a'), ('b_fixture', 'b')])
def test_sample(data_param, expected, request: pytest.FixtureRequest):
    data = request.getfixturevalue(data_param)
    assert data == expected

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question