在python中测试同一个函数的几个函数的更好方法

时间:2011-06-19 13:21:41

标签: python doctest repeat

假设一个包含大量函数的python文件,我想使用doctest为函数编写测试。例如,每个函数都接受一个字符串和一个连接对象(httplib.HTTPConnection(...))。所以如果字符串为空或None,我想测试每个函数。测试看起来像这样。

def function_1(mystring, conn):
    r'''
    >>> conn = httplib.HTTPConnection(...)
    >>> function_1(None, conn)
    Traceback (most recent call last):
    NoneAsInputError: `mystring` should be a string and not `None`!

    >>> function_1("", conn)
    Traceback (most recent call last):
    EmptyStringError: `mystring` should not be an empty string!
    '''

    pass

def function_2(mystring, conn):
    r'''
    >>> conn = httplib.HTTPConnection(...)
    >>> function_2(None, conn)
    Traceback (most recent call last):
    NoneAsInputError: `mystring` should be a string and not `None`!

    >>> function_2("", conn)
    Traceback (most recent call last):
    EmptyStringError: `mystring` should not be an empty string!
    '''

    pass

[...]

def function_n(mystring, conn):
    r'''
    >>> conn = httplib.HTTPConnection(...)
    >>> function_n(None, conn)
    Traceback (most recent call last):
    NoneAsInputError: `mystring` should be a string and not `None`!

    >>> function_n("", conn)
    Traceback (most recent call last):
    EmptyStringError: `mystring` should not be an empty string!
    '''

    pass

如您所见,测试是相同的,只有功能名称更改。是否有可能重构它以避免代码重复?

还是有更好的方法将这些测试混为一谈吗?

2 个答案:

答案 0 :(得分:4)

从未使用过doctest。

def genDocText(func_name):
    return r'''
    >>> conn = httplib.HTTPConnection(...)
    >>> %(func_name)s(None, conn)
    Traceback (most recent call last):
    NoneAsInputError: `mystring` should be a string and not `None`!

    >>> %(func_name)s("", conn)
    Traceback (most recent call last):
    EmptyStringError: `mystring` should not be an empty string!
    ''' % {'func_name': func_name}

def function_1(mystring, conn):
    pass

function_1.__doc__ = genDocText('function_1')

这是一种不好的方式吗?

<强>更新: 使用decorators上面的解决方案可以写成:

def genDocText(func):
    func.__doc__ = r'''
    >>> conn = httplib.HTTPConnection(...)
    >>> %(func_name)s(None, conn)
    Traceback (most recent call last):
    NoneAsInputError: `mystring` should be a string and not `None`!

    >>> %(func_name)s("", conn)
    Traceback (most recent call last):
    EmptyStringError: `mystring` should not be an empty string!
    ''' % {'func_name': func.__name__}
    return func

@genDocText
def function_1(mystring, conn):
    pass

@genDocText
def function_2(mystring, conn):
    pass

@genDocText
def function_n(mystring, conn):
    pass

if __name__ == '__main__':
    print function_1.__doc__
    print function_2.__doc__
    print function_n.__doc__

答案 1 :(得分:1)

这不是一个直接的答案,但我认为这是一个重要的观点:请考虑使用unittest进行严格的代码测试。 doctest很好但是它有限 - 除了确保文档中的简单代码片段真正起作用之外我不会用它做任何事情(注意 - 测试片段,不是模块)。

使用unittest,您可以添加到测试中的自定义数量非常无限,并且可以让您更彻底地测试代码。