Python のdoctest を試す
Python のdoctest を試す
簡単にテストできるdoctest についてのメモ。 unittest
モジュールより手軽に利用でき、 テスト駆動開発っぽいことができる。
環境
doctest
python で簡単にユニットテストできる。 docstring の中にテスト内容を書いておくだけでいい。 unittest
モジュールの完全代替は難しいと思われる。
int値を入力して、偶数か奇数かをチェックする関数をつくる。
テスト内容をdocstring の中 に書いておく。
>>> 関数(入力値)
期待する出力値
偶数チェックの関数なので、 以下のようなテスト内容にしておく。
...
>>> check_even(2)
True
>>> check_even(0)
True
>>> check_even(1)
False
...
また、メインにdoctest を実行する処理を書いておく。 これで、メインで実行した場合のみテストが行われる。
if __name__ == '__main__':
import doctest
doctest.testmod()
関数の中身は、まだ実装せず、 全体のソースとして、以下のようにしておく。
def check_even(n: int) -> bool:
'''
Function, check a even number.
Arg: int
Return: Bool
True: even
False: odd
>>> check_even(2)
True
>>> check_even(0)
True
>>> check_even(1)
False
'''
pass
if __name__ == '__main__':
import doctest
doctest.testmod()
テストの実行
テストするには、pythonコマンドに v
オプションをつけておくと、詳細なテスト結果がわかる。
python ファイル名.py -v
中身を実装していないので、 テストを実行して失敗するかを確認する。
実際に実行すると以下のような出力になる。
> python check_even.py -v
Trying:
check_even(2)
Expecting:
True
**********************************************************************
File "check_even.py", line 18, in __main__.check_even
Failed example:
check_even(2)
Expected:
True
Got nothing
Trying:
check_even(0)
Expecting:
True
**********************************************************************
File "check_even.py", line 20, in __main__.check_even
Failed example:
check_even(0)
Expected:
True
Got nothing
Trying:
check_even(1)
Expecting:
False
**********************************************************************
File "check_even.py", line 22, in __main__.check_even
Failed example:
check_even(1)
Expected:
False
Got nothing
1 items had no tests:
__main__
**********************************************************************
1 items had failures:
3 of 3 in __main__.check_even
3 tests in 2 items.
0 passed and 3 failed.
***Test Failed*** 3 failures.
実行結果にはunittestモジュール同様、 3タイプ「OK」,「Failed」, 「Error」がある。 「Error」 は、テストを実行前にプログラムが失敗しているので、 まず「Error」を失くすことから始める。
doctest にテスト内容を書いておけば、 メイン(if __name__ == '__main__'
)にテスト実行の処理を書かなくてもテストを実行できる。 python
コマンドに、 モジュールオプション(-m
)をつける。
python -m doctest -v ファイル名.py
テストのFailure を確認したので、 関数の中身を実装する。
def check_even(n:int) -> bool:
'''
Function, check a even number.
Arg: int
Return: Bool
True: even
False: odd
>>> check_even(2)
True
>>> check_even(0)
True
>>> check_even(1)
False
'''
if n % 2 == 0:
return True
return False
> python -m doctest -v check_even.py
Trying:
check_even(2)
Expecting:
True
ok
Trying:
check_even(0)
Expecting:
True
ok
Trying:
check_even(1)
Expecting:
False
ok
1 items had no tests:
check_even
1 items passed all tests:
3 tests in check_even.check_even
3 tests in 2 items.
3 passed and 0 failed.
Test passed.
テストが通っていることを確認。
raise Exception のテスト
doctest でもraise Exception のテストができる。
入力値の型がint かどうかをチェックする。 int
でなかったら、 raise NotIntError
を出すテストを追加する。
...
は、省略を表す。
>>> check_even(1.5)
Traceback (most recent call last):
...
check_even.NotIntError
型チェック実装前に、(テストを追加した以下のコードで)テストする。
class NotIntError(ValueError):
pass
def check_even(n:int) -> bool:
'''
Function, check a even number.
Arg: int
Return: Bool
True: even
False: odd
>>> check_even(2)
True
>>> check_even(0)
True
>>> check_even(1)
False
>>> check_even(1.5)
Traceback (most recent call last):
...
check_even.NotIntError
'''
if n % 2 == 0:
return True
return False
テスト結果はFailure になるはず。
> python -m doctest -v check_even.py
Trying:
check_even(2)
Expecting:
True
ok
Trying:
check_even(0)
Expecting:
True
ok
Trying:
check_even(1)
Expecting:
False
ok
Trying:
check_even(1.5)
Expecting:
Traceback (most recent call last):
...
check_even.NotIntError
**********************************************************************
File "C:\Users\nabana\GoogleDrive\python_workspace\check_even.py", line 27, in check_even
Failed example:
check_even(1.5)
Expected:
Traceback (most recent call last):
...
check_even.NotIntError
Got:
False
2 items had no tests:
check_even
check_even.NotIntError
**********************************************************************
1 items had failures:
1 of 4 in check_even.check_even
4 tests in 3 items.
3 passed and 1 failed.
***Test Failed*** 1 failures.
Failure を確認できたので、型チェックを実装してテストする。
class NotIntError(ValueError):
pass
def check_even(n:int) -> bool:
'''
Function, check a even number.
Arg: int
Return: Bool
True: even
False: odd
>>> check_even(2)
True
>>> check_even(0)
True
>>> check_even(1)
False
>>> check_even(1.5)
Traceback (most recent call last):
...
check_even.NotIntError
'''
if not isinstance(n, int):
raise NotIntError
if n % 2 == 0:
return True
return False
テスト結果がパスするか確認する。
> python -m doctest -v check_even.py
Trying:
check_even(2)
Expecting:
True
ok
Trying:
check_even(0)
Expecting:
True
ok
Trying:
check_even(1)
Expecting:
False
ok
Trying:
check_even(1.5)
Expecting:
Traceback (most recent call last):
...
check_even.NotIntError
ok
2 items had no tests:
check_even
check_even.NotIntError
1 items passed all tests:
4 tests in check_even.check_even
4 tests in 3 items.
4 passed and 0 failed.
Test passed.
参考リンク
関連リンク