3

紧跟在类或函数声明之后的 Python 文档字符串被放置在__doc__属性中。

问题:如何提取稍后在函数中出现的其他“内部”文档字符串?

更新:编译器省略了此类文字语句。我可以通过 AST 找到他们(以及他们的行号)吗?


我为什么要问?

我有一个(不完全成熟的)想法来使用这样的“内部”文档字符串来描述敏捷场景的 Given/When/Then 部分:

def test_adding():
    """Scenario: Adding two numbers"""
    adder = Adder()
    """When I add 2 and 3"""
    result = adder.add(2, 3)
    """Then the result is 5"""
    assert result == 5

通过提取文档字符串,测试运行框架可以生成如下输出:

Scenario: Adding two numbers
   When I add 2 and 3 (PASS)
   Then the result is 5 (FAIL)

AssertionError   Traceback
...

我认为这比 Behave 、 Freshen 、 Lettuce 、 PyCukes 中采用的方法更简洁后者需要每个步骤定义一个单独的函数。我不喜欢将步骤文本作为函数名称 ( @When("I add numbers") def add_numbers()) 重复。但与普通的单元测试不同,文档字符串将添加打印出业务可读场景以供参考的能力。

4

2 回答 2

4

您可以使用模块解析您的测试ast,并手动遍历树和设置测试等。可能有更好的方法来做到这一点(您可以使用ast.NodeVisitororast.NodeTransfomer和访问者模式),但这里有一个例子:

import ast, inspect

def find_tests(module):
    # generate AST from module's source
    tree = ast.parse(inspect.getsource(module))
    # return tests in module, assuming they are top level function definitions
    return [node for node in tree.body if isinstance(node, ast.FunctionDef)]

def print_docstrings(test):
    for node in test.body:
        if isinstance(node, ast.Expr):
            # print lineno and docstring
            print node.value.lineno, node.value.s

if __name__ == '__main__':
    import test_adding
    for test in find_tests(test_adding):
        print_docstrings(test)

您可能还对konira感兴趣。

于 2012-03-20T09:09:11.427 回答
2

你不能,因为编译器省略了文字语句。

>>> def foo():
...   'docstring'
...   3
...   'bar'
... 
>>> dis.dis(foo)
  4           0 LOAD_CONST               1 (None)
              3 RETURN_VALUE        
于 2012-03-20T07:26:54.570 回答