单元测试框架 - Doctest


Python 标准发行版包含“Doctest”模块。该模块的功能使得搜索看起来像交互式 Python 会话的文本片段成为可能,并执行这些会话以查看它们是否完全按照所示方式工作。

Doctest 在以下场景中非常有用 -

  • 通过验证所有交互式示例是否仍然按记录工作来检查模块的文档字符串是否是最新的。

  • 通过验证测试文件或测试对象中的交互式示例是否按预期工作来执行回归测试。

  • 为包编写教程文档,用输入输出示例进行大量说明

在 Python 中,“docstring”是一个字符串文字,它作为类、函数或模块中的第一个表达式出现。执行套件时它会被忽略,但编译器会识别它并放入封闭类、函数或模块的__doc__属性中。由于它可以通过内省获得,因此它是对象文档的规范位置。

通常的做法是将 Python 代码的不同部分的示例用法放在文档字符串中。doctest 模块允许验证这些文档字符串是否与代码中的间歇性修订保持同步。

在以下代码中,定义了阶乘函数并穿插了示例用法。为了验证示例用法是否正确,请调用 doctest 模块中的 testmod() 函数。

"""
This is the "example" module.

The example module supplies one function, factorial(). For example,

>>> factorial(5)
120
"""

def factorial(x):
   """Return the factorial of n, an exact integer >= 0.
   >>> factorial(-1)
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
   """
   
   if not x >= 0:
      raise ValueError("x must be >= 0")
   f = 1
   for i in range(1,x+1):
      f = f*i
   return f
   
if __name__ == "__main__":
   import doctest
   doctest.testmod()

输入上述脚本并将其保存为 FactDocTest.py 并尝试从命令行执行该脚本。

Python FactDocTest.py

除非示例失败,否则不会显示任何输出。现在,将命令行更改为以下内容 -

Python FactDocTest.py –v

控制台现在将显示以下输出 -

C:\Python27>python FactDocTest.py -v
Trying:
   factorial(5)
Expecting:
   120
ok
Trying:
   factorial(-1)
Expecting:
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
ok
2 items passed all tests:
   1 tests in __main__
   1 tests in __main__.factorial
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

另一方面,如果 Factorial() 函数的代码未在文档字符串中给出预期结果,则会显示失败结果。例如,在上面的脚本中将 f = 1 更改为 f = 2,然后再次运行 doctest。结果如下 -

Trying:
   factorial(5)
Expecting:
   120
**********************************************************************
File "docfacttest.py", line 6, in __main__
Failed example:
factorial(5)
Expected:
   120
Got:
   240
Trying:
   factorial(-1)
Expecting:
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
ok
1 items passed all tests:
   1 tests in __main__.factorial
**********************************************************************
1 items had failures:
   1 of 1 in __main__
2 tests in 2 items.
1 passed and 1 failed.
***Test Failed*** 1 failures.

Doctest:检查文本文件中的示例

doctest 的另一个简单应用是测试文本文件中的交互式示例。这可以通过 testfile() 函数来完成。

以下文本存储在名为“example.txt”的文本文件中。

Using ''factorial''
-------------------
This is an example text file in reStructuredText format. First import
''factorial'' from the ''example'' module:
   >>> from example import factorial
Now use it:
   >>> factorial(5)
   120

文件内容被视为文档字符串。为了验证文本文件中的示例,请使用 doctest 模块的 testfile() 函数。

def factorial(x):
   if not x >= 0:
      raise ValueError("x must be >= 0")
   f = 1
   for i in range(1,x+1):
      f = f*i
   return f
   
if __name__ == "__main__":
   import doctest
   doctest.testfile("example.txt")
  • 与 testmod() 一样,testfile() 不会显示任何内容,除非示例失败。如果示例确实失败,则失败的示例和失败的原因将使用与 testmod() 相同的格式打印到控制台。

  • 在大多数情况下,交互式控制台会话的复制和粘贴工作正常,但 doctest 并不尝试对任何特定的 Python shell 进行精确模拟。

  • 任何预期输出必须立即跟在包含代码的最后“>>>”或“...”行之后,并且预期输出(如果有)扩展到下一个“>>>”或全空白行。

  • 预期输出不能包含全空白行,因为这样的行用于表示预期输出的结束。如果预期的输出确实包含空行,请将 <BLANKLINE> 放入您的 doctest 示例中,每个地方都需要一个空行。