2010-01-06 5 views
0

unittest.assertRaises을 사용할 때 이상한 문제가 발생합니다. 아래 코드를 실행하면 다음과 같은 결과가 출력됩니다.assertRaises가 기본 예외를 catch합니다.

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 코드를 테스트하고 있습니다.

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

답변

1

derived.py를 실행하면 __main__ 모듈로 실행됩니다 (가져 오기가 아닌 직접 실행했기 때문에). 나중에이를 명시 적으로 가져 오면 모듈의 다른 사본이 만들어지며 이번에는 derived이라는 이름으로 작성됩니다. 따라서 __main__.MyErrorderived.MyError과 같지 않으며 예외는 발견되지 않습니다.

+0

아, 그 말이 맞습니다. 어떤 아이디어를 더 잘 구현할 수 있을까요? 예외를 다른 모듈로 옮기면 이미 작동하는 것으로 나타났습니다. – desolat

+0

예외를 이동하면이 문제가 해결되지만 동일한 모듈의 복사본이 두 개 계속 남아 있으며 나중에 다른 문제가 발생할 수 있습니다. 어떻게 든 주 모듈이 다른 모듈에 의해 반입되지 않도록해야합니다. 왜 당신이'BaseClass.get' 메소드가 필요한지 모르겠으니, 단위 테스트에서 호출하는 것을 피하기 위해 그것을 개선하는 방법을 말할 수는 없습니다. – interjay

0

문제는 당신 BaseClass.get() 방법 것이 아마도

은 기본 모듈 "bases.py"입니다 너에게 또 다른 반을 돌려주고있다. 그건 그렇고, 그 방법 자체가 끔찍한데 왜 내가이 일을하는지 궁금해.

+0

네, 그게 그 목적입니다. 이것은 인터페이스 구현을 그 이름으로 인스턴스화하는 일종의 추상 팩토리 인 전체 코드의 단순화 된 예제입니다. 어쨌든, 내 문제를 도와 주거나 호언 장담이 아닌 더 나은 구현을 제공한다면 감사하게 생각합니다. – desolat

+0

"그냥 호언 장담했다"! 나는 문제가 아마도'BaseClass.get()'이 당신에게'assertRaises'에 전달하는 클래스가 아닌 다른 클래스를 리턴 할 것이라고 지적했다. 'assertRaises'는 잘못이 아닙니다.이제 사람들이 코드 또는 디자인 스타일에 대해 의견을 제시하는 것을 좋아하지 않는다면 프로그래밍 질문을 인터넷에 게시하지 마십시오. –

+0

위 코드를 실행했다면 문제가 아님을 알았을 것입니다. 문제가 해결되지 않으면 이해하지 못하는 질문에 답하지 마십시오. 그것을하는 방법에 대한 대답을 참조하십시오. – desolat

2

mentioned 같이, 문제 __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:])) 

두 번 동일한 코드를 구문 분석에 낭비하는 동안,이 자체에 포함 된 교환입니다.

관련 문제