如何在单元测试中强调对输入数据的限制



我有参数化的测试,例如:

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 或类似名称,则还会在参数字段的顶部传达消息。

我不会添加断言或其他任何东西 - 无论如何,给出无效的时间字符串作为输入都会导致测试用例失败。

相关内容

  • 没有找到相关文章

最新更新