ProgramingTip

Python2.7의 unittest에서 assertRaises ()에 의해 생성 된 오류 메시지를 표시하는 방법은 무엇입니까?

bestdevel 2020. 11. 9. 20:07
반응형

Python2.7의 unittest에서 assertRaises ()에 의해 생성 된 오류 메시지를 표시하는 방법은 무엇입니까?


내 모듈의 오류 메시지가 유익한 지 확인하기 위해 assertRaises ()에 의해 잡힌 모든 오류 메시지를보고 싶습니다. 오늘은 assertRaises ()마다 수행하지만 테스트 코드에 많은 것이 있기 때문에 매우 지루합니다.

모든 assertRaises ()에 대한 대한 오류 메시지를 어떻게 인쇄 할 수 있습니까? 나는 그것을 해결하는 방법을 찾지 않고 http://docs.python.org/library/unittest.html 의 문서를 공부 합니다. 어떻게 든 assertRaises () 방법을 monkeypatch 할 수 있습니까? 나는 대부분의 경우 표준 방식으로 테스트 코드를 사용하기 때문에 테스트 코드의 모든 assertRaises () 줄을 변경하지 않는 것을 선호합니다.

이 질문은 Python unittest 와 관련이 많은 생각합니다 . 예외에서 인수를 어떻게 테스트합니까?

이것이 오늘 제가하는 방법입니다. 예를 들면 :

#!/usr/bin/env python

def fail():
    raise ValueError('Misspellled errrorr messageee')

그리고 테스트 코드 :

#!/usr/bin/env python
import unittest
import failure   

class TestFailureModule(unittest.TestCase):

    def testFail(self):
        self.assertRaises(ValueError, failure.fail)

if __name__ == '__main__':
    unittest.main()  

오류 메시지를 확인한 후 assertRaises ()의 오류 유형을 예를 들어 IOError로 변경합니다. 그런 다음 오류 메시지를 볼 수 있습니다.

 E
======================================================================
ERROR: testFail (__main__.TestFailureModule)
----------------------------------------------------------------------
Traceback (most recent call last):
 File "test_failure.py", line 8, in testFail
   self.assertRaises(IOError, failure.fail)
  File "/usr/lib/python2.7/unittest/case.py", line 471, in assertRaises
    callableObj(*args, **kwargs)
 File "/home/jonas/Skrivbord/failure.py", line 4, in fail
    raise ValueError('Misspellled errrorr messageee')
ValueError: Misspellled errrorr messageee

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

FAILED (errors=1)

어떤 제안? / 조나스

편집하다 :

Robert Rossney의 힌트를 통해 문제를 해결합니다. 주로 철자 오류를위한 것이 아니라 메시지가 모듈 사용자에게 실제로 확인하기위한 것입니다. unittest의 일반적인 기능 (대부분의 경우 사용하는 방법)은 SHOW_ERROR_MESSAGES = False를 설정하여 수행합니다.

방식으로 assertRaises () 메소드를 재정의합니다. 매력처럼 작동합니다!

SHOW_ERROR_MESSAGES = True

class NonexistantError(Exception):
    pass

class ExtendedTestCase(unittest.TestCase):
    def assertRaises(self, excClass, callableObj, *args, **kwargs):
        if SHOW_ERROR_MESSAGES:
            excClass = NonexistantError
        try:
            unittest.TestCase.assertRaises(self, excClass, callableObj, *args, **kwargs)
        except:
            print '\n    ' + repr(sys.exc_info()[1]) 

결과 출력의 일부 :

testNotIntegerInput (__main__.TestCheckRegisteraddress) ... 
    TypeError('The registeraddress must be an integer. Given: 1.0',)

    TypeError("The registeraddress must be an integer. Given: '1'",)

    TypeError('The registeraddress must be an integer. Given: [1]',)

    TypeError('The registeraddress must be an integer. Given: None',)
ok
testCorrectNumberOfBytes (__main__.TestCheckResponseNumberOfBytes) ... ok
testInconsistentLimits (__main__.TestCheckNumerical) ... 
    ValueError('The maxvalue must not be smaller than minvalue. Given: 45 and 47, respectively.',)

    ValueError('The maxvalue must not be smaller than minvalue. Given: 45.0 and 47.0, respectively.',)
ok
testWrongValues (__main__.TestCheckRegisteraddress) ... 
    ValueError('The registeraddress is too small: -1, but minimum value is 0.',)

    ValueError('The registeraddress is too large: 65536, but maximum value is 65535.',)
ok
testTooShortString (__main__.TestCheckResponseWriteData) ... 
    ValueError("The payload is too short: 2, but minimum value is 4. Given: '\\x00X'",)

    ValueError("The payload is too short: 0, but minimum value is 4. Given: ''",)

    ValueError("The writedata is too short: 1, but minimum value is 2. Given: 'X'",)

    ValueError("The writedata is too short: 0, but minimum value is 2. Given: ''",)
ok
testKnownValues (__main__.TestCreateBitPattern) ... ok
testNotIntegerInput (__main__.TestCheckSlaveaddress) ... 
    TypeError('The slaveaddress must be an integer. Given: 1.0',)

    TypeError("The slaveaddress must be an integer. Given: '1'",)

    TypeError('The slaveaddress must be an integer. Given: [1]',)

    TypeError('The slaveaddress must be an integer. Given: None',)
ok


기본적 unittest으로이 작업을 수행하지 않습니다. 이 작업을 자주 수행하고 싶은 경우 다음과 같이 시도 할 수 있습니다.

class ExtendedTestCase(unittest.TestCase):

  def assertRaisesWithMessage(self, msg, func, *args, **kwargs):
    try:
      func(*args, **kwargs)
      self.assertFail()
    except Exception as inst:
      self.assertEqual(inst.message, msg)

ExtendedTestCase대신 에서 단위 테스트 클래스를 가져옵니다 unittest.TestCase.

그러나 실제로 맞춤법이 틀린 오류 메시지에 대해 우려하고 그에 대한 테스트 케이스를 구축하고 싶은 경우 메시지를 문자열 리터럴로 인라인해서는 안됩니다. 다른 중요한 문자열로 수행하는 작업을 수행해야합니다. 가져 오는 모듈에서 상수로 정의하고 누군가가 교정을 담당하고 있습니다. 코드에서 단어 철자를 잘못 입력 한 개발자는 테스트 케이스에서도 철자를 잘못 입력합니다.


나는 한때 @Robert Rossney가 위에 제시 한 가장 훌륭한 대답을 선호했습니다. 요즘에는 assertRaises를 컨텍스트 관리자 (unittest2의 새로운 기능)로 사용하는 것을 선호합니다.

with self.assertRaises(TypeError) as cm:
    failure.fail()
self.assertEqual(
    'The registeraddress must be an integer. Given: 1.0',
    str(cm.exception)
)

Python 2.7부터 사용할 수있는 assertRaisesRegexp를 찾고 있습니다. 문서에서 :

self.assertRaisesRegexp(ValueError, 'invalid literal for.*XYZ$', int, 'XYZ')

또는:

with self.assertRaisesRegexp(ValueError, 'literal'):
    int('XYZ')

오류 메시지가 정확히 일치하려는 경우 :

with self.assertRaises(ValueError) as error:
  do_something()
self.assertEqual(error.exception.message, 'error message')

mkelley33은 좋은 대답을 제공하지만이 접근 방식은 Codacy 와 같은 일부 코드 분석 도구에서 문제로 감지 될 수 있습니다 . 문제는 assertRaises컨텍스트 관리자로 사용할 수 있다는 것을 모르고 모든 인수가 assertRaises method에 전달되지는 않는다고보고한다는 입니다.

따라서 Robert의 Rossney 답변을 개선하고 싶습니다.

class TestCaseMixin(object):

    def assertRaisesWithMessage(self, exception_type, message, func, *args, **kwargs):
        try:
            func(*args, **kwargs)
        except exception_type as e:
            self.assertEqual(e.args[0], message)
        else:
            self.fail('"{0}" was expected to throw "{1}" exception'
                      .format(func.__name__, exception_type.__name__))

주요 차이점은 다음과 같습니다.

  1. 예외 유형을 테스트합니다.
  2. 이 코드는 Python 2와 Python 3 모두에서 실행할 수 있습니다 ( e.args[0]Py3의 오류에는 message속성 이 없기 때문에 호출 합니다).

참고 URL : https://stackoverflow.com/questions/8672754/how-to-show-the-error-messages-caught-by-assertraises-in-unittest-in-python2-7

반응형