我有参数化测试,例如:
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
)。我如何强调它 - 在docstring中,或者使用assert输入数据?
使用docstring
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
还是有其他方法?
我会在评论或测试函数docstring中说一个胖警告就足够了。这不是应该验证的不可信用户输入;另外,最好让测试尽可能简单。如果某些开发人员在没有首先阅读文档的情况下滥用测试输入,那么现在就是他自己的错。
但是,使用pytest
肯定可以进行测试args验证(例如,告知开发人员测试函数没有任何问题,并且他们使用的测试错误)。我会使用间接参数化进行隐式args验证。在下面的示例中,来自mark.parametrize
的每个arg将首先传递到具有相同名称的fixture,您可以在测试开始之前进行预处理:
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 ================================
有关间接参数化的更多信息:Deferring the setup of parametrized resources
你当然可以添加额外的评论等。但是,您已经有了一些自然的地方来表达您的意图:您的测试函数可以被赋予比test_good_input
更具描述性的名称,您的测试函数的参数可以被赋予更多的描述性名称,变量,辅助函数等都可以具有描述性名。
例如,您可以将测试函数命名为test_getNextHour_withValidTimeString_shouldGiveOneHourLaterTimeString
。我认为这说明了一切。如果将t_str
重命名为valid_time_str
或类似的东西,这还会在参数字段的顶部传达消息。
我不会添加断言或其他 - 给出无效的时间字符串作为输入将导致失败的测试用例无论如何。