8

有没有办法编写 python doctest 字符串来测试旨在从命令行(终端)启动的脚本,该脚本不会使用 os.popen 调用污染文档示例?

#!/usr/bin/env python
# filename: add
"""
Example:
>>> import os
>>> os.popen('add -n 1 2').read().strip()
'3'
"""

if __name__ == '__main__':
    from argparse import ArgumentParser
    p = ArgumentParser(description=__doc__.strip())
    p.add_argument('-n',type = int, nargs   = 2, default = 0,help  = 'Numbers to add.')
    p.add_argument('--test',action = 'store_true',help  = 'Test script.')
    a = p.parse_args()
    if a.test:
        import doctest
        doctest.testmod()
    if a.n and len(a.n)==2:
        print a.n[0]+a.n[1]

在不使用 popen 的情况下运行 doctest.testmod() 只会导致测试失败,因为脚本是在 python shell 而不是 bash(或 DOS)shell 中运行的。

LLNL的高级 Python 课程建议将脚本放在与 .py 模块分开的文件中。但随后 doctest 字符串仅测试模块,没有 arg 解析。而且我的 os.popen() 方法污染了示例文档。有没有更好的办法?

4

3 回答 3

4

刚刚找到了一些看起来像您想要的答案的东西: shell-doctest

于 2012-07-12T05:14:21.203 回答
1

doctest旨在运行python代码,因此您必须在某处进行转换。如果您决定通过 直接测试命令行界面doctest,一种可能性是__doc__在将其传递给之前进行正则表达式替换argparse,以取出os.popen包装器:

clean = re.sub(r"^>>> os\.popen\('(.*)'\).*", r"% \1", __doc__)
p = ArgumentParser(description=clean, ...)

(当然有各种更好的方法可以做到这一点,这取决于你认为什么“好”)。

这将为最终用户清理它。如果您还希望它在源代码中看起来更干净,您可以采用另一种方式:将命令行示例放在 docstring 中,不要使用 doctest.testmodule()。运行您的文档字符串doctest.script_from_examples并对其进行后处理以插入os调用。(然后您必须将其嵌入到某些东西中,以便您可以使用run_docstring_examples.doctest

>>> print doctest.script_from_examples("""
Here is a commandline example I want converted:
>>> add -n 3 4
7
""")
# Here is a commandline example I want converted:
add -n 3 4
# Expected:
## 7

这仍然会>>>在帮助中显示 python 提示。如果这让您感到困扰,您可能只需要在两个方向上处理字符串。

于 2012-04-02T11:50:44.303 回答
1

您也可以自己加载文档字符串并执行命令,就像在这个测试中一样。

import sys

module = sys.modules[__name__]
docstring = module.__doc__
# search in docstring for certain regex, and check that the following line(s) matches a pattern.
于 2019-08-21T17:03:53.643 回答