LoginSignup
0
2

More than 5 years have passed since last update.

python docstring内にテストを記述

Last updated at Posted at 2016-10-09

doctestモジュールのdoctest.testmod()関数はdocstring内にテストを記述し、verboseモードで実行することでテストが実行される

今まではこう書いてたところ

sample.py
def twice(n):
    """ 引数を 2 倍して返す関数
    >>> twice(8)
    16
    >>> twice(1850923)
    """
    return n * 2


'''TEST
twice(8)
 # 実行結果
 #16
twice(1850923)
 # 実行結果
 #3701846
'''# ←ここのトリプルクォートを'TEST'って書いてあるところまで引き上げてやることでtwice(8), twice(1850923)を実行する

TEST下のトリプルクォートをTESTのところまで上げてやるとdocstring的な複数行コメントアウトが外れ、実行したときにtwice関数が実行されてテストされる。
そのTESTってやつは関数より下にあるから、見た目が悪い。
できることならdocstringにまとめたい。

doctestモジュールを使う

しかしdoctestモジュールを使えばdocstring内に記述できて、他のモジュールから実行したときに実行させない、器用なことができる

doctest_sample.py
def twice(n):
    """ 引数を 2 倍して返す関数
    >>> twice(8)
    16
    >>> twice(1850923)
    3701846
    """
    return n * 2


print('name?>>', __name__)
if __name__ == "__main__":
    doctest.testmod()

print('EOF')

実行結果を以下の4つの方法で検証

  1. ipython
    1. %run doctest_sample -v
    2. %run doctest_use.py -v
  2. sublimetext
    1. sublimetext上でdoctest_sample.pyを実行
    2. sublimetext上でdoctest_use.py.pyを実行 > doctest_use.py.pyの内容はimportを行うだけ >>python:doctest_sample.use.py import doctest_sample

ipython上でpythonファイルを実行するときは'%run 'でrunする。
doctest.testmod()を使うときはverboseモード-vで実行する。

sublimetext上で実行するときはctrl+bでbuildする。
verboseモードの実行はデフォルトでは入ってない(嘘か本当か未検証)のでbuildシステムを作ってUserディレクトリに保存
メニュー>ツール>Buile systemから作成したPython_Verboseを選択してctrl+b

Python_Verbose.sublime-build
{
    "cmd": ["python", "$file", "-v"],
    "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
    "selector": "source.python"
}

コマンドライオプション-uと-vについて

1 コマンドラインと環境(http://docs.python.jp/3.3/using/cmdline.html)
1.1 コマンドライン
1.1.3 その他のオプション

-u¶(原文)

Force the binary layer of the stdout and stderr streams (which is available as their buffer attribute) to be unbuffered. The text I/O layer will still be line-buffered if writing to the console, or block-buffered if redirected to a non-interactive file.

PYTHONUNBUFFERED も参照してください。

-v

モジュールが初期化されるたびに、それがどこ(ファイル名やビルトインモジュール) からロードされたのかを示すメッセージを表示します。 2重に指定された場合(-vv)は、モジュールを検索するときにチェックされた各ファイルに対してメッセージを表示します。また、終了時のモジュールクリーンアップに関する情報も提供します。 PYTHONVERBOSE も参照してください。

結果1.1 ipython上で%run doctest_sample -v

1.1
In [80]: run doctest_sample.py -v
name?>> __main__
Trying:
    twice(8)
Expecting:
    16
ok
Trying:
    twice(1850923)
Expecting:
    3701846
ok
1 items had no tests:
    __main__
1 items passed all tests:
   2 tests in __main__.twice
2 tests in 2 items.
2 passed and 0 failed.
Test passed.
EOF

name属性がmainなので、doctestが実行される
doctestの記述は
>>>で書いたところでpython形式で実行し、結果を返す
エラーがなければokと出して次のテストに進む。

1.1
Trying:
    twice(8)
Expecting:
    16
ok

テストサマリーを表示する

1.1
1 items had no tests:
    __main__
1 items passed all tests:
   2 tests in __main__.twice
2 tests in 2 items.
2 passed and 0 failed.
Test passed.
body...

結果1.2 ipython上で%run doctest_use -v

1.2
In [81]: run doctest_use.py

出力が何も表示されない。

結果2.1 sublimetext上でdoctest_sample.pyをbuild

2.1
name?>> __main__
Trying:
    twice(8)
Expecting:
    16
ok
Trying:
    twice(1850923)
Expecting:
    3701846
ok
1 items had no tests:
    __main__
1 items passed all tests:
   2 tests in __main__.twice
2 tests in 2 items.
2 passed and 0 failed.
Test passed.
EOF
[Finished in 0.5s]

sublimetextのビルド結果に表れる[Finished in 0.5s]以外1.1の結果と同じ

結果2.2 sublimetext上でdoctest_use.pyをbuild

2.2
name?>> doctest_sample
EOF
[Finished in 0.4s]

結果1.2と異なりprint文は実行されるようだ。

まとめ

  • docstring内にテストを記述する
  • docstring.testmod()を記述する
    • name属性がmainの時に実行するようif文の中に入れておく(doc.py参照)
  • pythonをverboseモードで実行する(python <filename> -v)
doc.py
import docstring

def hoge():
    '''
    hoge(args)
    '''


if __name__ == "__main__":
    doctest.testmod()

参考

Python でテスト
コマンドラインと環境

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2