doctestライブラリ
pythonには関数定義の直後に ''' foo bar buzz '''
みたいにして関数の説明書きみたいなのを入れられる。これをdocstring
という。doctestはこのdocstring
を使って関数の動作テストもしちゃおうっていう話。
使ってみた
概要
なにか関数書かないといけないわけで。factorial
とか普通すぎるのでfizzbuzz
にした。pythonにはone liner
という縛りがあって、ここのコードを使ってみました。
fizzbuzz.py
def fizzbuzz(n):
"""
This function returns a list whose elements are
converted into fizzbuzz form.
>>> fizzbuzz(10)
[1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7, 8, 'Fizz', 'Buzz']
>>> len(fizzbuzz(9))
9
>>> fizzbuzz(10) + 1
Traceback (most recent call last):
File "/Users/yourname/python/fizbuzz.py", line 32, in <module>
fizzbuzz(10) + 1
TypeError: can only concatenate list (not "int") to list
"""
for i in range(1,n+1): res.append("FizzBuzz"[(i**2)%3*4:8--(i**4)%5] or i)
return res
if __name__ == '__main__':
import doctest
doctest.testmod()
FizzBuzz関数について
ちょこっと説明すると、"FizzBuzz"という文字列を切り分けてプリントしている。:
で区切った左右の数を調整することで所望のストリングを切り出しているというわけ。要するに
case(i):
iが [3の倍数] かつ [5の倍数]:
"FizzBuzz"[0:8]
iが [3の倍数] かつ [5の倍数ではない]:
"FizzBuzz"[0:4]
iが [3の倍数ではない] かつ [5の倍数]:
"FizzBuzz"[4:8]
iが [3の倍数ではない] かつ [5の倍数ではない]:
"FizzBuzz"[4:4] /* Empty String => None */
ということ。これを実現するためには、3の倍数の時に0、その他は4
のものと、5の倍数の時に8、その他は4
というものを用意すればいい。one-linerなので無理やり剰余で頑張ってるけど、別に関数つくってもいいと思う。
感想
エラーが起きるとこうなる
ちなみにシミュレートしたのは、返す値を増やした場合。
**********************************************************************
File "/Users/hiroberry/python/foo.py", line 8, in __main__.fizzbuzz
Failed example:
len(fizzbuzz(9))
Expected:
10
Got:
9
**********************************************************************
1 items had failures:
1 of 3 in __main__.fizzbuzz
***Test Failed*** 1 failures.
[Finished in 0.1s]
一目瞭然。便利すぎでしょう。
Tracebackについて
動かない例ををわざわざ作って試してみた。Traceback以下の文はぴったり一致してる必要はなさそう。どうやら、TypeError: can only ...
の文だけを見ているようだ。