0

を使用すると、奇妙な問題が発生しunittest.assertRaisesます。以下のコードを実行すると、次の出力が得られます。

E
======================================================================
ERROR: testAssertRaises (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\home\python_test\src\derived.py", line 29, in testAssertRaises
    self.assertRaises(MyError, self.raiser.raiseMyError)
  File "C:\Programme\Python26\lib\unittest.py", line 336, in failUnlessRaises
    callableObj(*args, **kwargs)
  File "C:\home\python_test\src\derived.py", line 15, in raiseMyError
    raise MyError("My message")
MyError: 'My message'

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)

正しい例外が発生しますが、テストは失敗します! 私がキャッチしている場合BaseError、テストは成功します。

どういうわけか、これは unittest がMyError例外クラスを認識できないというスコープの問題のようです。誰かがそれを説明できますか?回避策はありますか?

クラス名でオブジェクトを動的に構築するための実装である次の Python コードをテストしています。

これはベース モジュール「bases.py」です。

class BaseClass(object):

    @staticmethod
    def get(className):
        module = __import__("derived", globals(), locals(), [className])
        theClass = getattr(module, className)
        return theClass()


class BaseError(Exception):

    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        return repr(self.msg)

これは、テストするモジュール「derived.py」です。

import unittest

from bases import BaseError
from bases import BaseClass


class MyErrorRaiser(BaseClass):    

    def raiseMyError(self):
        raise MyError("My message")


class MyError(BaseError):
    '''
    '''


class Test(unittest.TestCase):

    def setUp(self):
        self.raiser = BaseClass.get("MyErrorRaiser")

    def testAssertRaises(self):
        self.assertRaises(MyError, self.raiser.raiseMyError)


if __name__ == "__main__":
    unittest.main()
4

3 に答える 3

2

前述のように、問題はモジュール__main__であり、派生したものは同じではありません。この答えは、それをどのように修正するかについてです。

モジュールコードとスクリプトコードを混在させないでください。if __name__ == "__main__"コードをハックと考え始めてください。(それでも時々非常に便利で、デバッグなどに頻繁に使用しますが、ハックと見なすので、常に少し頭を悩ませることができます。)すべてを実行する新しいスクリプトは単純です(そして決してインポート):

#!/usr/bin/env python
import derived
import sys
sys.exit(derived.main(sys.argv[1:]))

または個人的な好みによってさまざまな違いがあります。必要なことを行うには、必ずderived.mainを追加してください。

また、derived.pyの上部に、あまり一般的ではない別のハックもあります。

import sys
if __name__ == "__main__":
  import derived # import the same module under its "correct" name
  sys.exit(derived.main(sys.argv[1:]))

同じコードを2回解析するのは無駄ですが、これは自己完結型です。

于 2010-01-06T17:36:31.087 に答える
1

derived.py を実行すると、__main__モジュールとして実行されます (インポートするのではなく、直接実行したため)。後で明示的にインポートすると、モジュールの別のコピーが作成されますが、今回は という名前で作成されますderived。So__main__.MyErrorは と同じではなくderived.MyError、例外はキャッチされません。

于 2010-01-06T13:13:48.897 に答える
0

問題はおそらく、BaseClass.get()メソッドが別のクラスを返していることです。ところで、その方法自体がひどいのに、どうしてこんなことをしているのだろう。

于 2010-01-06T13:11:42.167 に答える