在 python 中测试同一事物的多个函数的更好方法

发布于 2024-11-15 22:07:55 字数 1475 浏览 3 评论 0原文

假设一个 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

正如您所看到的,测试是相同的,只是函数名称发生了变化。是否可以重构以避免代码重复?

或者有没有更好的方法来整合这些测试?

Assuming a python file with a whole bunch of functions I want to write tests for the functions using doctest. For example every function takes a string and a connection object (httplib.HTTPConnection(...)). So I want to test every function if the string is empty or None. The tests would look like this.

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

As you can see, the test are identical, only the function name changes. Is it possible to refactor that to avoid code repetition?

Or is there a better way to lump together such tests?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

羞稚 2024-11-22 22:07:55

从未使用过 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')

这是一个坏方法吗?

更新
使用 装饰器 上面的解决方案可以写成:

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__

Never used 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')

Is this a bad way?

UPDATE:
Using decorators the solution above can be written as:

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__
心如荒岛 2024-11-22 22:07:55

这不是一个直接的答案,但我认为这是一个重要的观点:请考虑使用 unittest 对代码进行任何认真的测试。 doctest 很好,但它是有限的 - 除了确保文档中的简单代码片段确实有效之外,我不会将它用于任何其他用途(注意 - 测试片段,而不模块)。

使用 unittest,您可以在测试中添加无限量的自定义,并且它允许您更彻底地测试代码。

This is not a direct answer, but I think it's an important point to make: Please consider using unittest for any serious testing of your code. doctest is nice but it's limited - I wouldn't use it for anything beyond making sure simple snippets of code in the documentation really work (note - testing the snippets, not the module).

With unittest you're quite limitless in the amount of customization you can add to your tests and it will allow you to test your code much more thoroughly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文