Python - unittestのassertRaisesの使い方
数日前からPython2.7を勉強し始めています。
WEBチュートリアルを少しずつやっているんですが、充実度がすごい。
そんな訳でPythonに標準で入っているunittestを使い、
assertRaisesにて例外のテストを書こうとしました。
(noseとかpy.testとかの方が便利らしいですが、
まずは標準の状態でアレコレしたかったのでunittestにしてます)
こんなふうに。
import unittest class MyException(Exception): pass class Target: def something(self): raise MyException class Test(unittest.TestCase): def setUp(self): self.target = Target() def test_exception(self): self.assertRaises(MyException, self.target.something()) if __name__ == '__main__': unittest.main()
しかしテストを実行すると失敗しました。
E
======================================================================
ERROR: test_exception (__main__.Test)
- -
Traceback (most recent call last):
File "/Users/kanno/.vim_sandbox/2013-05-01-2014.py", line 15, in test_exception
self.assertRaises(MyException, self.target.something())
File "/Users/kanno/.vim_sandbox/2013-05-01-2014.py", line 8, in something
raise MyException
MyException
- -
Ran 1 test in 0.000s
FAILED (errors=1)
あれーと思ってググったら見つかったこちらのサイト。
Python/Unittest : assertRaises raises Error | loup2fu
To avoid this error, simply run the function using lambda in the test call :
lambda使っちゃいなよ、ということなので書き換えることに。
def test_exception(self): self.assertRaises(MyException, lambda: self.target.something())
そしたら通りました。
.
- -
Ran 1 test in 0.000s
OK
で、なんか違うなと思いつつTwitterに呟いたところ
unittestのassertRaisesで期待通りに例外投げてるのにテスト落ちちゃって何でだってなったのだけど、とあるサイトにlambdaでラップしろってあって確かに動いたけどそういうものなのか
@methaneさんに教えて頂きました。ありがとうございます!
@kanno_kanno Python ですか? assertRaises(Error, spam(a, b)) だと assertRaises が呼ばれる前にすでに例外飛んでしまってるので、 assertRaises(Error, spam, (a, b)) みたいにするか、
@kanno_kanno with self.assertRaises(): spam(a, b) する必要があります。URL
こう書くか、
def test_exception(self): # NG: self.target.something() # OK: self.target.something self.assertRaises(MyException, self.target.something)
こう書いてバッチリ!
def test_exception(self): with self.assertRaises(MyException): self.target.something()
まとめ
ドキュメントちゃんと読め