У меня есть параметризованный тест, например:
import pytest
from datetime import time
def get_next_hour(time_str: str):
t = time(*map(int, time_str.split(':')))
new_t = time((t.hour + 1) % 24, t.minute)
return new_t.strftime('%H:%M')
@pytest.mark.parametrize(
"t_str, result_str",
[
('10:30', '11:30'),
('11:30', '12:30'),
]
)
def test_good_input(t_str, result_str):
result = get_next_hour(t_str)
assert result == result_str
Тест test_good_input должен работать только с допустимыми строками времени (для некорректных данных у меня есть другой тест test_bad_input). Как я могу это подчеркнуть - в строке документации или используя утверждение для входных данных?
Со строкой документации
def test_good_input(t_str, result_str):
"""for t_str allowed only time-valid strings"""
result = get_next_hour(t_str)
assert result == result_str
С проверочным вводом
def test_good_input(t_str, result_str):
assert ':' in t_str, 'input data is not time'
result = get_next_hour(t_str)
assert result == result_str
Или есть другие способы?
@hoefling Да, я так и делаю, но если другой разработчик (или я через несколько месяцев) добавит новые параметризованные аргументы, я хотел бы напомнить, какими они должны быть.






Я бы сказал, что толстого предупреждения в комментарии или строки документации тестовой функции должно быть достаточно. Это не ненадежный пользовательский ввод, который следует проверить; Кроме того, лучше, чтобы тесты были как можно более простыми. Если какой-то разработчик неправильно использует тестовые входные данные, не прочитав сначала документы, теперь это его собственная вина.
Тем не менее, проверка тестовых аргументов, безусловно, возможна с pytest (например, чтобы сообщить разработчикам, что с тестируемой функцией все в порядке, и они используют тест неправильно). Я бы сделал неявную проверку аргументов, используя косвенную параметризацию. В приведенном ниже примере каждый аргумент из mark.parametrize будет сначала передан фикстуре с тем же именем, где вы сможете выполнить предварительную обработку перед началом теста:
def validate(input):
try:
datetime.strptime(input, '%H:%M')
except ValueError as e:
pytest.fail('Your test parametrization is wrong. The test argument is erroneous: {}'.format(e))
@pytest.fixture
def t_str(request):
validate(request.param)
return request.param
@pytest.fixture
def result_str(request):
validate(request.param)
return request.param
@pytest.mark.parametrize(
"t_str, result_str",
[
('10:30', '11:30'),
('11:30', '12:30'),
('10:30', 'bar'),
],
indirect=True
)
def test_good_input(t_str, result_str):
...
Теперь третий тест завершится ошибкой с описательным сообщением об ошибке:
test_spam.py::test_good_input[10:30-11:30] PASSED
test_spam.py::test_good_input[11:30-12:30] PASSED
test_spam.py::test_good_input[10:30-bar] ERROR
============================================= ERRORS ==============================================
__________________________ ERROR at setup of test_good_input[10:30-bar] ___________________________
...
input = 'bar'
def validate(input):
try:
datetime.strptime(input, '%H:%M')
except ValueError as e:
> pytest.fail('Your test parametrization is wrong. The test argument is erroneous: {}'.format(e))
E Failed: Your test parametrization is wrong. The test argument is erroneous: time data 'bar' does not match format '%H:%M'
test_spam.py:15: Failed
================================ 2 passed, 1 error in 0.05 seconds ================================
Дополнительная информация о косвенной параметризации: Откладывание настройки параметризованных ресурсов
Вы, конечно, можете добавить дополнительные комментарии или тому подобное. Но у вас уже есть некоторые естественные места для выражения ваших намерений: вашей тестовой функции можно дать более описательное имя, чем test_good_input, аргументам вашей тестовой функции можно дать более описательные имена, а переменные, вспомогательные функции и т. д. — все они могут иметь описательные имена. имена.
Например, вы можете назвать свою тестовую функцию test_getNextHour_withValidTimeString_shouldGiveOneHourLaterTimeString. Я бы сказал, что этим все сказано. Если вы переименуете t_str в valid_time_str или что-то подобное, это дополнительно передает сообщение также в верхней части поля параметра.
Я бы не стал добавлять утверждения или что-то еще - ввод недопустимой строки времени в качестве входных данных в любом случае приведет к неудачному тестовому случаю.
Разве вы уже не подчеркиваете это, указывая аргументы в
mark.parametrize?