如何在Python中编写和使用doctest来编写docstrings的测试代码。

商业

Python 自带了一个标准的 doctest 模块,可以测试 docstring 的内容,这使得在 docstring 中写输入和输出的例子变得很容易,也使得文档更容易理解。

这里提供了以下信息。

  • 用doctest进行测试的一个简单例子
    • 如果没有错误
    • 如果有一个错误
  • 通过选项和参数控制输出结果
    • -v选项
    • verbose参数(如函数、程序、方案)
  • 从命令行运行doctest模块
  • 在一个外部文本文件中编写测试
    • 如何编写一个文本文件
    • 从py文件中调用
    • 直接执行一个文本文件

用doctest进行测试的一个简单例子

docstring是一个字符串,它包含了以下内容之一。(1) 要测试的函数的名称,(2) 要测试的函数的名称,(3) Python 交互模式下的预期输出值。

  • """
  • '''

如果没有错误

确保函数和文件串内容中的代码是正确的。

def add(a, b):
    '''
    >>> add(1, 2)
    3
    >>> add(5, 10)
    15
    '''

    return a + b


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

运行这个文件。

$ python3 doctest_example.py

如果没有错误,就不会有任何输出。

if __name__ == '__main__'这意味着 “只有在从命令行执行相应的脚本文件时才执行后续处理。

如果有一个错误

如果你创建并执行以下错误的代码,将输出一个错误。

def add(a, b):
    '''
    >>> add(1, 2)
    3
    >>> add(5, 10)
    10
    '''

    return a * b


if __name__ == '__main__':
    import doctest
    doctest.testmod()
$ python3 doctest_example_error.py
**********************************************************************
File "doctest_example_error.py", line 3, in __main__.add
Failed example:
    add(1, 2)
Expected:
    3
Got:
    2
**********************************************************************
File "doctest_example_error.py", line 5, in __main__.add
Failed example:
    add(5, 10)
Expected:
    10
Got:
    50
**********************************************************************
1 items had failures:
   2 of   2 in __main__.add
***Test Failed*** 2 failures.

它显示如下。

预期的输出值写在doctest中。Expected
实际输出值Got

通过选项和参数控制输出结果

-v选项

如果你想在没有错误时也显示输出结果,请在命令行上用-v选项运行该命令。

$ python3 doctest_example.py -v
Trying:
    add(1, 2)
Expecting:
    3
ok
Trying:
    add(5, 10)
Expecting:
    15
ok
1 items had no tests:
    __main__
1 items passed all tests:
   2 tests in __main__.add
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

verbose参数(如函数、程序、方案)

如果你想总是显示输出结果,在py文件中的doctest.testmod()中指定参数verbose=True。

if __name__ == '__main__':
    import doctest
    doctest.testmod(verbose=True)

在运行时,输出结果将总是在没有-v选项的情况下显示。

$ python3 doctest_example_verbose.py
Trying:
    add(1, 2)
Expecting:
    3
ok
Trying:
    add(5, 10)
Expecting:
    15
ok
1 items had no tests:
    __main__
1 items passed all tests:
   2 tests in __main__.add
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

从命令行运行doctest模块

if __name__ == '__main__'如果你想在其中做其他事情,你可以直接从命令行运行doctest模块,而不需要在py文件中调用doctest.testmod()。

例如,在以下情况下

def add(a, b):
    '''
    >>> add(1, 2)
    3
    >>> add(5, 10)
    15
    '''

    return a + b


if __name__ == '__main__':
    import sys
    result = add(int(sys.argv[1]), int(sys.argv[2]))
    print(result)

它可以接收命令行参数并像往常一样执行进程。

$ python3 doctest_example_without_import.py 3 4
7

如果你用-m选项以脚本形式运行doctest,测试将针对doctest所在的函数运行。如果你想显示输出结果,像以前一样加上-v。

$ python3 -m doctest doctest_example_without_import.py

$ python3 -m doctest -v doctest_example_without_import.py
Trying:
    add(1, 2)
Expecting:
    3
ok
Trying:
    add(5, 10)
Expecting:
    15
ok
1 items had no tests:
    doctest_example_without_import
1 items passed all tests:
   2 tests in doctest_example_without_import.add
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

在一个外部文本文件中编写测试

你也可以把测试代码写在一个外部文本文件中,而不是写在文档串中。

如何编写一个文本文件

以Python交互式模式格式编写,如docstring所描述。有必要导入要使用的函数。

如果你想把文本文件和要测试的.py文件放在同一目录下,只需按如下方式导入。

>>> from doctest_example import add
>>> add(1, 2)
3
>>> add(5, 10)
15

从py文件中调用

在另一个.py文件中调用doctest.testfile()进行测试。

指定编写测试代码的文本文件的路径作为doctest.testfile()的参数。

import doctest
doctest.testfile('doctest_text.txt')

运行这个py文件。

$ python3 doctest_example_testfile.py -v
Trying:
    from doctest_example import add
Expecting nothing
ok
Trying:
    add(1, 2)
Expecting:
    3
ok
Trying:
    add(5, 10)
Expecting:
    15
ok
1 items passed all tests:
   3 tests in doctest_text.txt
3 tests in 1 items.
3 passed and 0 failed.
Test passed.

直接执行一个文本文件

即使你没有py文件,你也可以直接从命令行读取文本文件并运行测试。

用-m选项运行Python命令,将doctest作为一个脚本运行。你可以指定文本文件的路径作为命令行参数。

$ python3 -m doctest -v doctest_text.txt
Trying:
    from doctest_example import add
Expecting nothing
ok
Trying:
    add(1, 2)
Expecting:
    3
ok
Trying:
    add(5, 10)
Expecting:
    15
ok
1 items passed all tests:
   3 tests in doctest_text.txt
3 tests in 1 items.
3 passed and 0 failed.
Test passed.