Я хочу параметризовать тест для 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
маркера result_matrix
. Но могу ли я достичь того же, используя существующие инструменты? Пожалуйста, примите во внимание решение, которое будет хорошо работать для потенциально бесконечного числа входных параметров.
Я сомневаюсь, что есть решение для действительно бесконечного числа параметров, но вы можете попробовать следующее:
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) Вы также можете проверить структуру гипотез, которая основана на концепции случайного тестирования, что делает проверку функции более обширной.
x
и y
но это делает тесты менее сложными, чем в моем примере с индексом. Я понимаю, что мое идеальное решение может быть не столь очевидным для понимания.
x
иy
будут продублированы.