Skip to main content

Python 代码测试

Python 文档测试

文档测试(doctest)是Python内置的测试工具,通过在函数、类或模块的文档字符串(docstring)中嵌入测试用例,验证代码行为。它结合了文档和测试,适合快速验证代码的正确性。doctest通过模拟交互式Python会话,检查代码输出是否与预期一致。

编写第一个doctest

文档测试通常写在函数的文档字符串中,格式为>>>后跟代码,下一行是预期输出。以下是一个简单示例:

def add(a, b):
    """加法函数。
    
    >>> add(2, 3)
    5
    >>> add(-1, 1)
    0
    """
    return a + b

if __name__ == "__main__":
    import doctest
    doctest.testmod()

运行此代码时,doctest.testmod()会扫描文档字符串中的测试用例,执行并验证输出。无错误时无输出,有错误则显示失败详情。

doctest的语法规则

  • 测试用例以>>>开头,模拟Python交互式环境。
  • 预期输出紧跟在>>>代码的下一行,无需额外符号。
  • 多行输出需精确匹配,包括换行和空格。
  • 异常测试使用>>>后跟Traceback描述,例如:
def divide(a, b):
    """除法函数。
    
    >>> divide(6, 2)
    3.0
    >>> divide(5, 0)
    Traceback (most recent call last):
        ...
    ZeroDivisionError: division by zero
    """
    return a / b

if __name__ == "__main__":
    import doctest
    doctest.testmod()

测试复杂输出

对于复杂数据结构(如列表或字典),确保输出格式一致。可以使用doctest的选项标志(如+ELLIPSIS)简化匹配:

def get_list():
    """返回一个列表。
    
    >>> get_list()  # doctest: +ELLIPSIS
    [...]
    """
    return [1, 2, 3]

if __name__ == "__main__":
    import doctest
    doctest.testmod()

+ELLIPSIS允许用...匹配任意内容,适合不可预测的输出部分。

在模块级别编写doctest

模块级别的doctest写在模块顶部的文档字符串中,适合测试全局函数或模块行为:

"""
这是一个计算平方和的模块。

>>> square_sum(3, 4)
25
"""
def square_sum(a, b):
    return a**2 + b**2

if __name__ == "__main__":
    import doctest
    doctest.testmod()

使用doctest运行测试

有三种方式运行doctest:

  1. 代码内运行:如上,使用doctest.testmod()
  2. 命令行运行:保存代码为example.py,运行python -m doctest example.py -v-v显示详细输出)。
  3. 集成到unittest:将doctest嵌入unittest框架:
import doctest
import unittest

def multiply(a, b):
    """乘法函数。
    
    >>> multiply(2, 3)
    6
    >>> multiply(0, 5)
    0
    """
    return a * b

def load_tests(loader, tests, ignore):
    tests.addTests(doctest.DocTestSuite())
    return tests

if __name__ == "__main__":
    unittest.main()

doctest的优缺点

优点

  • 测试与文档结合,易于维护。
  • 简单易用,适合快速验证。
  • 内置模块,无需额外安装。

缺点

  • 不适合复杂测试场景(如依赖外部资源)。
  • 输出格式需严格匹配,维护成本可能较高。
  • 难以测试非确定性输出。