13

関数で例外が発生するかどうかをチェックする次のテストコードがあります。テストに合格することを期待していますが、代わりに失敗が示されます。テストコードは次のとおりです。

import unittest

# define a user-defined exception
class MyException(Exception):
    def __str__(self):
        return repr("ERROR: Just raised my exception!")

# this is my main class with a method raising this exception
class MyMainObject(object):

    def func(self):
        raise MyException()

# the test class
class TestConfig(unittest.TestCase):

    def test_1(self):

        other = MyMainObject()
        self.assertRaises(MyException, other.func())

# calling the test
if __name__ == '__main__':    
    unittest.main()

other.func()assertステートメントで呼び出されると、MyExceptionが発生します(簡単に確認できます)。したがって、テストは、で失敗するassertRaisesので、テストに合格する必要がありますが、次のようになります。other.func()MyException

....
MyException: 'ERROR: Just raised my exception!'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

何か問題はないと思いますので、この問題についてご意見をいただければ幸いです。

4

2 に答える 2

29

assertRaises関数を呼び出します。自分で呼び出すと、テストする前に例外が発生します。 assertRaises

コードを次のように変更します。

self.assertRaises(MyException, other.func)

そしてそれは正しく動作します。または、コンテキストマネージャーとして使用することもできますassertRaises(Python 2.7以降)。

with self.assertRaises(MyException):
    other.func()

コンテキストマネージャーとして使用assertRaisesすると、例外インスタンスを取得してさらにテストを実行できるという追加の利点があります。

with self.assertRaises(MyException) as raises_cm:
    other.func()

exception = raises_cm.exception
self.assertEqual(exception.args, ('foo', 'bar'))
于 2012-09-20T16:31:40.983 に答える
7

言語の規則により、呼び出された関数のコードが入力される前に引数が評価されます(これは一般的に良いことです)。したがって、assertRaises引数の評価中に発生する例外をキャッチすることはできません。回避策(複数のAPIで)は、呼び出し可能オブジェクトをのようなメソッドに渡すことです。これにより、メソッドはassertRaises、制御できる場所と例外をキャッチできる場所でそれを評価できます。引数全体がメソッド呼び出しである場合、バインドされたメソッドの魔法により、このような愚かさなしにlambda、またはそのような愚かさなしに、これを非常にエレガントに述べることができます。

self.assertRaises(MyException, other.func) # <- note, no parentheses after func
于 2012-09-20T16:31:38.690 に答える