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に呟いたところ

@methaneさんに教えて頂きました。ありがとうございます!


こう書くか、

  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()

まとめ

ドキュメントちゃんと読め