Programing

python unittest-assertRaises의 반대?

lottogame 2020. 3. 5. 22:46
반응형

python unittest-assertRaises의 반대?


주어진 상황에서 예외가 발생하지 않도록 테스트를 작성하고 싶습니다.

예외 발생 했는지 테스트하는 것은 간단합니다 ...

sInvalidPath=AlwaysSuppliesAnInvalidPath()
self.assertRaises(PathIsNotAValidOne, MyObject, sInvalidPath) 

...하지만 어떻게 반대 를 할 수 있습니까 ?

내가 좋아하는이 같은 것 ...

sValidPath=AlwaysSuppliesAValidPath()
self.assertNotRaises(PathIsNotAValidOne, MyObject, sValidPath) 

def run_test(self):
    try:
        myFunc()
    except ExceptionType:
        self.fail("myFunc() raised ExceptionType unexpectedly!")

Hi-주어진 상황에서 예외가 발생하지 않는지 확인하기 위해 테스트를 작성하고 싶습니다.

이것이 기본 가정입니다. 예외는 발생하지 않습니다.

다른 말을하지 않으면 모든 단일 테스트에서 가정됩니다.

실제로 어떤 주장을 쓰지 않아도됩니다.


그냥 함수를 호출하십시오. 예외가 발생하면 단위 테스트 프레임 워크에서이를 오류로 표시합니다. 다음과 같은 주석을 추가 할 수 있습니다.

sValidPath=AlwaysSuppliesAValidPath()
# Check PathIsNotAValidOne not thrown
MyObject(sValidPath)

나는 원래 포스터이며 코드에서 먼저 사용하지 않고 DGH의 위 답변을 수락했습니다.

일단 사용하고 나면 실제로 필요한 작업을 수행하기 위해 약간의 조정이 필요하다는 것을 깨달았습니다 (DGH에게 공정하게하기 위해 "또는 비슷한 것"이라고 말함!).

다른 사람들의 이익을 위해 여기에 조정을 게시 할 가치가 있다고 생각했습니다.

    try:
        a = Application("abcdef", "")
    except pySourceAidExceptions.PathIsNotAValidOne:
        pass
    except:
        self.assertTrue(False)

여기서 시도한 것은 공백의 두 번째 인수로 Application 객체를 인스턴스화하려고 시도하면 pySourceAidExceptions.PathIsNotAValidOne이 발생하는지 확인하는 것입니다.

위의 코드 (DGH의 답변에 크게 기반)를 사용하면 그렇게 할 것이라고 믿습니다.


모듈 에서 assertNotRaises원래 구현의 약 90 %를 재사용하여 정의 할 수 있습니다 . 이 방법을 사용하면 반전 된 실패 조건을 제외 하고와 동일하게 동작 하는 방법이 생깁니다 .assertRaisesunittestassertNotRaisesassertRaises

TLDR 및 라이브 데모

assertNotRaises메소드 를 추가하는 것은 놀랍게도 쉬운 것으로 판명되었습니다 unittest.TestCase(코드와 마찬가지로이 답변을 작성하는 데 약 4 배가 걸렸습니다). 다음 은 실제 assertNotRaises작동 하는 방법의 데모입니다 . 그냥 같은assertRaises , 당신도에 호출 및 인수를 전달할 수 있습니다 assertNotRaises, 또는 당신은 그것을 사용할 수 있습니다 with문. 라이브 데모에는 assertNotRaises의도 한대로 작동 하는 테스트 사례가 포함되어 있습니다.

세부

assertRaisesin 구현 unittest은 상당히 복잡하지만 약간의 영리한 서브 클래 싱을 사용하면 실패 조건을 무시하고 되돌릴 수 있습니다.

assertRaises기본적으로 unittest.case._AssertRaisesContext클래스 의 인스턴스를 작성 하고 리턴 하는 짧은 메소드입니다 ( unittest.case모듈 의 정의 참조 ). 메소드를 _AssertNotRaisesContext서브 클래 싱 _AssertRaisesContext하고 재정 의하여 고유 한 클래스를 정의 할 수 있습니다 __exit__.

import traceback
from unittest.case import _AssertRaisesContext

class _AssertNotRaisesContext(_AssertRaisesContext):
    def __exit__(self, exc_type, exc_value, tb):
        if exc_type is not None:
            self.exception = exc_value.with_traceback(None)

            try:
                exc_name = self.expected.__name__
            except AttributeError:
                exc_name = str(self.expected)

            if self.obj_name:
                self._raiseFailure("{} raised by {}".format(exc_name,
                    self.obj_name))
            else:
                self._raiseFailure("{} raised".format(exc_name))

        else:
            traceback.clear_frames(tb)

        return True

일반적으로 테스트 케이스 클래스를에서 상속하여 테스트 케이스 클래스를 정의합니다 TestCase. 대신 하위 클래스에서 상속하는 경우 MyTestCase:

class MyTestCase(unittest.TestCase):
    def assertNotRaises(self, expected_exception, *args, **kwargs):
        context = _AssertNotRaisesContext(expected_exception, self)
        try:
            return context.handle('assertNotRaises', args, kwargs)
        finally:
            context = None

모든 테스트 사례에 이제 assertNotRaises사용할 수 있는 방법이 있습니다.


에 예외 클래스를 전달하면 assertRaises()컨텍스트 관리자가 제공됩니다. 이렇게하면 테스트의 가독성이 향상 될 수 있습니다.

# raise exception if Application created with bad data
with self.assertRaises(pySourceAidExceptions.PathIsNotAValidOne):
    application = Application("abcdef", "")

이를 통해 코드에서 오류 사례를 테스트 할 수 있습니다.

이 경우 PathIsNotAValidOne응용 프로그램 생성자에 잘못된 매개 변수를 전달할 때 발생 하는 테스트 입니다.


unittest다음과 같이 monkey-patch하는 것이 유용하다는 것을 알았습니다 .

def assertMayRaise(self, exception, expr):
  if exception is None:
    try:
      expr()
    except:
      info = sys.exc_info()
      self.fail('%s raised' % repr(info[0]))
  else:
    self.assertRaises(exception, expr)

unittest.TestCase.assertMayRaise = assertMayRaise

이를 통해 예외가 없는지 테스트 할 때 의도가 명확 해집니다.

self.assertMayRaise(None, does_not_raise)

또한 루프에서 테스트를 단순화하여 종종 내가하는 일을 발견합니다.

# ValueError is raised only for op(x,x), op(y,y) and op(z,z).
for i,(a,b) in enumerate(itertools.product([x,y,z], [x,y,z])):
  self.assertMayRaise(None if i%4 else ValueError, lambda: op(a, b))

def _assertNotRaises(self, exception, obj, attr):                                                                                                                              
     try:                                                                                                                                                                       
         result = getattr(obj, attr)                                                                                                                                            
         if hasattr(result, '__call__'):                                                                                                                                        
             result()                                                                                                                                                           
     except Exception as e:                                                                                                                                                     
         if isinstance(e, exception):                                                                                                                                           
            raise AssertionError('{}.{} raises {}.'.format(obj, attr, exception)) 

매개 변수를 승인해야하는 경우 수정 될 수 있습니다.

처럼 전화

self._assertNotRaises(IndexError, array, 'sort')

당신은 그렇게 시도 할 수 있습니다. try : self.assertRaises (None, function, arg1, arg2) 예외 : try 블록 안에 코드를 넣지 않으면 'AssertionError : None not raised'예외를 통해 테스트 케이스가 실패합니다. 시도 블록 안에 넣으면 동작이 예상됩니다.

참고 URL : https://stackoverflow.com/questions/4319825/python-unittest-opposite-of-assertraises



반응형