@kicherov_maxim

Как использовать фикстуры в параметризации тестов?

Добрый день, у меня есть тест, и я бы хотел запускать его параметризовано.
фикстуры

@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': 'name@company.ru',
        '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
    }


тест без параметризации работает
@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))


неудачная попытка параметризации
@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))

во первых декоратор не видит фикстуру, приходится добавлять from tests.fixtures import bank, хотя она объявлена в conftest, и когда я передавал ее в тест в рабочем первом примере все работало нормально. Во вторых я получаю ошибку
AttributeError: 'function' object has no attribute.

Еще я попробывать так
@mark.parametrize('control, model, document', [(BanksControl, Bank, bank())])

И получил Fixture "bank" called directly. Fixtures are not meant to be called directly, but are created automatically when test functions request them as parameters.

Подскажите пожалуйста как запустить тест с разными параметрами?
  • Вопрос задан
  • 775 просмотров
Решения вопроса 1
@twistfire92
Python backend developer
Вам надо в параметрах передавать название фикстуры, а в тесте вытаскивать ее через request
Вот пример

# 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
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы