有时候我们想在 Python 中做一些测试,比如测试刚写的类的方法是否运行正常,或者测试代码是否产生预期异常。这种情况下使用 unittest 是麻烦且费事的,因为我们需要直观的在代码中看到这些测试,并且能运行这些测试。
doctest 模块为我们提供了一种在 Python docstring 中写测试用例并进行测试的方法。
在 Python 的官方文档中,对 doctest 的介绍是这样的:
doctest 模块会搜索那些看起来像是 Python 交互式会话中的代码片段,然后尝试执行并验证结果。
源码中的 doctest
1 | # test_doctest.py |
测试:
1 | $ python doctest_test.py |
有两个地方可以放 doctest 的测试用例,一个位置是模块的开头,令一个位置是函数声明语句的下一行(如上例)。除此之外其他地方的 doctest 都无效,即使放了也不会被执行。
doctest 在 docstring 中寻找测试用例的时候,认为 >>>
是一个测试用例的开始,直到遇到空行或者下一个 >>>
,在两个测试用例之间的其他内容会被 doctest 忽略掉。
当 __main__
函数不方便调用 doctest 的时候,可以使用另一种执行方法:
1 | $ python -m doctest test_doctest.py |
-v
参数用于输出详细信息。
独立文件中的 doctest
如果不想把 doctest 内嵌于 Python 源码中,可以建立一个独立文件来保存测试用例。
1 | test_doctest.txt |
然后执行:
1 | $ python -m doctest -v test_doctest.txt |
这里注意,from
一行也要以 >>>
开头。
处理可变变量
测试过程中,有些内容是不断变化的,如时间、对象ID等等。
1 | # test_changable.py |
直接运行这个测试用例必然失败,因为对象在内存中的位置是不固定的。这个时候我们可以使用 doctest 的 ELLOPSIS
开关,并在需要忽略的地方用 ...
代替。
1 | # test_new_changable.py |
测试结果:
1 | $ python -m doctest test_new_changable.py -v |
交互器跨多行
1 | # test_multiline.py |
测试结果:
1 | $ python -m doctest test_multiline.py -v |
异常
Traceback 是一种特殊的可变变量,因为 Traceback 中的信息会随着系统平台、脚本文件位置变化而变化,所以匹配 Traceback 的时候我们需要忽略一些东西。可以只写第一行的 Traceback (most recent call last):
或者 Traceback (innermost last):
和最后一行的异常信息即可。
1 | # test_exception.py |
测试结果:
1 | $ python -m doctest test_exception.py -v |
处理空白字符
有时测试用例的输出中会有空行、空格等空白字符,然而 doctest 默认空行代表测试用例的结束,这是我们可以用 <BLANKLINE>
代表空行。
1 | # test_blankline.py |
测试结果:
1 | $ python -m doctest -v test_blankline.py |
关于 doctest 常用的就这么多,更多内容请参考官方文档。