3

クラスまたは関数の宣言の直後に続くPythondocstringは、__doc__属性に配置されます。

質問:関数の後半で発生する追加の「内部」docstringをどのように抽出しますか?

更新:このようなリテラルステートメントは、コンパイラーによって省略されます。おそらく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

docstringを抽出することにより、テスト実行フレームワークは次のような出力を生成できます。

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

AssertionError   Traceback
...

これは、 BehaveFreshenLettucePyCukesで採用されているアプローチよりも簡潔であり、ステップごとに個別の関数を定義する必要があると思います。ステップのテキストを関数名()として繰り返す必要はありません@When("I add numbers") def add_numbers()。ただし、単純な単体テストとは異なり、docstringは、参照用にビジネスで読み取り可能なシナリオを印刷する機能を追加します。

4

2 に答える 2

4

モジュールを使用してテストを解析しast、ツリーを手動でウォークしてテストをセットアップするなどの方法があります。これを行うにはおそらくより良い方法があります(ast.NodeVisitorまたはast.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)

コニラにも興味があるかもしれません。

于 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 に答える