我有参数化的测试,例如:
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
(。我如何强调它 - 在文档字符串中,还是对输入数据使用 assert?
带文档字符串
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
还是有其他方法?
我会说注释或测试函数文档字符串中的胖警告应该就足够了。这不是应验证的不受信任的用户输入;此外,最好使测试尽可能简单。如果某些开发人员在没有先阅读文档的情况下滥用测试输入,那么现在是他自己的错。
但是,测试参数验证肯定可以通过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
或类似名称,则还会在参数字段的顶部传达消息。
我不会添加断言或其他任何东西 - 无论如何,给出无效的时间字符串作为输入都会导致测试用例失败。