Pytest. Лучший способ определить ожидаемый результат при использовании составных параметрических декораторов? - PullRequest
1 голос
/ 18 апреля 2020

У меня есть два одинаковых тестовых случая, в каждом из которых более 100 строк кода, которые создают вспомогательные объекты для теста, эти строки очень похожи, на самом деле, только две строки отличаются между настройками теста, и я не хочу избавляться повторения кода. Я думаю, что множественная параметризация может помочь мне с этой задачей. Используя множественную параметризацию, я могу объединить настройки в одну и фактически обеспечить лучшие условия для теста. Булочка Я не могу обернуть голову, что является лучшим способом для определения ожидаемого результата при использовании множественной параметризации, когда каждая комбинация даст разные результаты?

Рассмотрим этот тестовый пример

@pytest.mark.parametrize('country', ['US', 'DE', 'FR', 'IT'])
@pytest.mark.parametrize('number', ['12345', '54321'])
def test_correct_record_is_selected_for_number(country, number):
    # 100 line long setup of different objects.
    record = get_record(country, number)
    assert record = expected_record

Я ожидаю, что для различных комбинаций (country, number) get_record функция будет возвращать разные результаты, и я вижу единственный способ обеспечить ожидаемый результат - это переопределить часть функции get_record logi c в самом тесте, чтобы определить, какой результат ожидать на основе предоставленных country и number, что мне не кажется правильным.

Есть ли способ красиво указать ожидаемый вывод для сложенных parametrize декораторов? Или мне лучше перенести код настройки на несколько разных приборов и оставить его в виде 2 отдельных тестов, в которых используются разные приборы?

Ответы [ 2 ]

2 голосов
/ 18 апреля 2020

Я не знаю хорошего способа, но в любом случае вы должны где-то перечислить разные ожидаемые результаты. Таким образом, вы можете просто поместить их в словарь вне теста:

expected_record = {
    'US': {
        '12345': {...},
        '54321': {...}
    },
    'DE': {
        '12345': {...},
        '54321': {...}'
    },
    ...
}

@pytest.mark.parametrize('country', ['US', 'DE', 'FR', 'IT'])
@pytest.mark.parametrize('number', ['12345', '54321'])
def test_correct_record_is_selected_for_number(country, number):
    record = get_record(country, number)
    assert record == expected_record[country][number]
1 голос
/ 18 апреля 2020

Обычно я помещаю результаты в отдельный прибор, который выбирает ожидаемое значение на основе других аргументов. Пример:

expected_records = {'US': {'12345': 'fizz', '54321': 'buzz'}, 'DE': ...}


@pytest.fixture
def expected_record(request):
    country = request.node.funcargs['country']
    number = request.node.funcargs['number']
    return expected_records.get(country, dict()).get(number, None)


@pytest.mark.parametrize('country', ['US', 'DE', 'FR', 'IT'])
@pytest.mark.parametrize('number', ['12345', '54321'])
def test_correct_record_is_selected_for_number(country, number, expected_record):
    record = get_record(country, number)
    assert record == expected_record

Однако на практике данные редко жестко закодированы в скрипте, поэтому логический c из expected_record обычно управляется данными, например:

@pytest.fixture
def expected_record(request):
    country = request.node.funcargs['country']
    number = request.node.funcargs['number']
    file = pathlib.Path(request.config.rootdir, 'data', country).with_suffix('.json') # data/DE.json
    data = json.loads(file.read_text())  # {12345: "fizz", 54321: "buzz"}
    return data[number]
...