pytest - минимальное обслуживание для параметризации результатов «таблицы умножения» - PullRequest
0 голосов
/ 30 августа 2018

Я хочу параметризовать тест для 2 входных значений и одного выходного значения, которое можно сравнить с таблицей умножения тестирования. Чтобы добиться минимального обслуживания, я придумал что-то вроде этого:

results = [[ 4,  5,  6],
           [ 8, 10, 12],
           [12, 15, 18]]

@pytest.mark.parametrize("x, ix", [(1, 0), (2, 1), (3, 2)])
@pytest.mark.parametrize("y, iy", [(4, 0), (5, 1), (6, 2)])
def test_multiplication(x, ix, y, iy):
    assert x * y == results[ix][iy]

Теперь, это не идеально, потому что, если я хочу добавить новые x, тогда мне придется добавить len(y) + 1 + 1 значений, которые являются: 3 новыми ожидаемыми значениями, дополнительными x значениями и индексами , В идеале было бы добавить только 4 значения, то есть без управляющей переменной для индекса. Мне также не нравится, как results отделены от тестовой функции. Идеальным было бы:

@pytest.mark.parametrize("x", [1, 2, 3])
@pytest.mark.parametrize("y", [4, 5, 6])
@pytest.mark.result_matrix("result", [
    [ 4,  5,  6],
    [ 8, 10, 12],
    [12, 15, 18],
])
def test_multiplication(x, y, result):
    assert x * y == result

Я знаю, что могу сам добавить поддержку для такого маркера result_matrix. Но могу ли я достичь того же, используя существующие инструменты? Пожалуйста, примите во внимание решение, которое будет хорошо работать для потенциально бесконечного числа входных параметров.

1 Ответ

0 голосов
/ 21 сентября 2018

Я сомневаюсь, что есть решение для действительно бесконечного числа параметров, но вы можете попробовать следующее:

1) Как и @ ev-br, укажите все параметры функций в одном операторе parametrize, но вы должны подготовить их перед этим в конструкторе для этих аргументов.

2) сделать то же самое в цикле for над теми же аргументами. Это менее необычно, чем mark.parametrize, но часто более читабельно.

3) заставить ваш тест параметризации или цикл for принять список словарей с аргументами и результатом:

# code under test
def foo(x, y):
    return x * y

# need a constructor code for these test arguments and results
d0=dict(args=dict(x=2, y=3), result=6)
d1=dict(args=dict(x=5, y=10), result=50)
params = [d0, d1]

# test prototype - goes to pytest
for d in params:
    assert foo(**d['args']) == d['result'] 

Я думаю, что эта часть наиболее близка к вашей концепции принятия большого количества аргументов.

4) Возможно, вы захотите проверить гипотезу фреймворка, который работает на основе концепции случайного тестирования, что делает проверку функции более обширной.

...