문제

함수가 예상 예외를 던지지 않는 경우에만 실패하는 장치를 어떻게 작성합니까?

도움이 되었습니까?

해결책

사용 TestCase.assertRaises (또는 TestCase.failUnlessRaises) 예를 들어 UnitTest 모듈에서 :

import mymod

class MyTestCase(unittest.TestCase):
    def test1(self):
        self.assertRaises(SomeCoolException, mymod.myfunc)

다른 팁

Python 2.7이므로 Context Manager를 사용하여 실제 예외 객체가 발생할 수 있습니다.

import unittest

def broken_function():
    raise Exception('This is broken')

class MyTestCase(unittest.TestCase):
    def test(self):
        with self.assertRaises(Exception) as context:
            broken_function()

        self.assertTrue('This is broken' in context.exception)

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

http://docs.python.org/dev/library/unittest.html#unittest.testcase.assertraises


~ 안에 파이썬 3.5, 당신은 포장해야합니다 context.exception 안에 str, 그렇지 않으면 당신은 얻을 수 있습니다 TypeError

self.assertTrue('This is broken' in str(context.exception))

이전 답변의 코드는 다음과 같이 단순화 할 수 있습니다.

def test_afunction_throws_exception(self):
    self.assertRaises(ExpectedException, afunction)

그리고 불만이 논쟁을 취하면 다음과 같은 어시스트로 전달하십시오.

def test_afunction_throws_exception(self):
    self.assertRaises(ExpectedException, afunction, arg1, arg2)

파이썬 함수가 예외를 던지는 것을 어떻게 테스트합니까?

함수가 예상 예외를 던지지 않는 경우에만 실패하는 테스트를 어떻게 작성합니까?

짧은 대답:

사용 self.assertRaises 맥락 관리자로서의 방법 :

    def test_1_cannot_add_int_and_str(self):
        with self.assertRaises(TypeError):
            1 + '1'

데모

모범 사례 접근법은 파이썬 쉘에서 시연하기가 상당히 쉽습니다.

그만큼 unittest 도서관

Python 2.7 또는 3에서 :

import unittest

Python 2.6에서는 2.7의 백 포트를 설치할 수 있습니다. unittest 도서관 UnitTest2, 그리고 그냥 그다지 별명 unittest:

import unittest2 as unittest

예제 테스트

이제 Python의 유형 안전성에 대한 다음 테스트를 파이썬 쉘에 붙여 넣으십시오.

class MyTestCase(unittest.TestCase):
    def test_1_cannot_add_int_and_str(self):
        with self.assertRaises(TypeError):
            1 + '1'
    def test_2_cannot_add_int_and_str(self):
        import operator
        self.assertRaises(TypeError, operator.add, 1, '1')

하나를 테스트합니다 assertRaises 컨텍스트 관리자로서 기록 된 상태에서 오류가 올바르게 잡히고 정리되도록합니다.

우리는 또한 그것을 쓸 수 있습니다 없이 컨텍스트 관리자는 테스트 2를 참조하십시오. 첫 번째 인수는 당신이 기대하는 오류 유형, 두 번째 인수, 테스트하는 기능 및 나머지 Args 및 키워드 Args가 해당 함수로 전달됩니다.

컨텍스트 관리자를 사용하는 것이 훨씬 간단하고 읽기 쉬우 며 유지 관리 가능하다고 생각합니다.

테스트 실행

테스트를 실행하려면 :

unittest.main(exit=False)

Python 2.6에서는 아마도있을 것입니다 다음이 필요합니다:

unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))

그리고 터미널은 다음을 출력해야합니다.

..
----------------------------------------------------------------------
Ran 2 tests in 0.007s

OK
<unittest2.runner.TextTestResult run=2 errors=0 failures=0>

그리고 우리는 우리가 기대하는대로 1 그리고 a '1' 결과 a TypeError.


더 많은 장황한 결과를 얻으려면 다음을 시도하십시오.

unittest.TextTestRunner(verbosity=2).run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))

코드는이 패턴을 따라야합니다 (이것은 UnitTest 모듈 스타일 테스트입니다) :

def test_afunction_throws_exception(self):
    try:
        afunction()
    except ExpectedException:
        pass
    except Exception as e:
       self.fail('Unexpected exception raised:', e)
    else:
       self.fail('ExpectedException not raised')

Python <2.7 에서이 구성은 예상 예외에서 특정 값을 확인하는 데 유용합니다. UnitTest 기능 assertRaises 예외가 제기 된 경우에만 확인합니다.

에서: http://www.lengrand.fr/2011/12/pythonunittest-assertraises-raiss-error/

먼저, 여기에 파일 dum_function.py의 해당 (Still Dum : P) 함수가 있습니다.

def square_value(a):
   """
   Returns the square value of a.
   """
   try:
       out = a*a
   except TypeError:
       raise TypeError("Input should be a string:")

   return out

수행 할 테스트는 다음과 같습니다 (이 테스트 만 삽입) :

import dum_function as df # import function module
import unittest
class Test(unittest.TestCase):
   """
      The class inherits from unittest
      """
   def setUp(self):
       """
       This method is called before each test
       """
       self.false_int = "A"

   def tearDown(self):
       """
       This method is called after each test
       """
       pass
      #---
         ## TESTS
   def test_square_value(self):
       # assertRaises(excClass, callableObj) prototype
       self.assertRaises(TypeError, df.square_value(self.false_int))

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

우리는 이제 우리의 기능을 테스트 할 준비가되었습니다! 테스트를 실행할 때 발생하는 일은 다음과 같습니다.

======================================================================
ERROR: test_square_value (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_dum_function.py", line 22, in test_square_value
    self.assertRaises(TypeError, df.square_value(self.false_int))
  File "/home/jlengrand/Desktop/function.py", line 8, in square_value
    raise TypeError("Input should be a string:")
TypeError: Input should be a string:

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

FAILED (errors=1)

TypeError는 Actullay가 올라가고 테스트 실패를 생성합니다. 문제는 이것이 바로 우리가 원하는 행동이라는 것입니다.

이 오류를 피하려면 테스트 호출에서 Lambda를 사용하여 기능을 실행합니다.

self.assertRaises(TypeError, lambda: df.square_value(self.false_int))

최종 출력 :

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

OK

완벽한 !

... 그리고 나도 완벽 해요 !!

Julien Lengrand-Lambert 씨

직접 만들 수 있습니다 contextmanager 예외가 제기되었는지 확인합니다.

import contextlib

@contextlib.contextmanager
def raises(exception):
    try:
        yield 
    except exception as e:
        assert True
    else:
        assert False

그런 다음 사용할 수 있습니다 raises 이와 같이:

with raises(Exception):
    print "Hola"  # Calls assert False

with raises(Exception):
    raise Exception  # Calls assert True

사용중인 경우 pytest, 이것은 이미 구현되었습니다. 넌 할 수있어 pytest.raises(Exception):

예시:

def test_div_zero():
    with pytest.raises(ZeroDivisionError):
        1/0

그리고 결과 :

pigueiras@pigueiras$ py.test
================= test session starts =================
platform linux2 -- Python 2.6.6 -- py-1.4.20 -- pytest-2.5.2 -- /usr/bin/python
collected 1 items 

tests/test_div_zero.py:6: test_div_zero PASSED

나는 사용한다 DocTest1] 거의 모든 곳에서 내 기능을 동시에 문서화하고 테스트한다는 사실이 마음에 들기 때문입니다.

이 코드를 살펴보십시오.

def throw_up(something, gowrong=False):
    """
    >>> throw_up('Fish n Chips')
    Traceback (most recent call last):
    ...
    Exception: Fish n Chips

    >>> throw_up('Fish n Chips', gowrong=True)
    'I feel fine!'
    """
    if gowrong:
        return "I feel fine!"
    raise Exception(something)

if __name__ == '__main__':
    import doctest
    doctest.testmod()

이 예제를 모듈에 넣고 명령 줄에서 실행하면 두 테스트 사례가 평가되고 확인됩니다.

[1] 파이썬 문서 : 23.2 DocTest- 테스트 대화식 파이썬 예제

살펴보십시오 Assertraises 방법의 방법 unittest 기준 치수.

나는 방금 그것을 발견했다 모의 도서관 AsserTraisesWithMessage () 메소드 (UnitTest.testcase 서브 클래스)를 제공합니다. 이는 예상 예외가 제기 될뿐만 아니라 예상되는 메시지로 제기되는지 확인합니다.

from testcase import TestCase

import mymod

class MyTestCase(TestCase):
    def test1(self):
        self.assertRaisesWithMessage(SomeCoolException,
                                     'expected message',
                                     mymod.myfunc)

UnitTest 모듈에서 AsserTraises를 사용할 수 있습니다

import unittest

class TestClass():
  def raises_exception(self):
    raise Exception("test")

class MyTestCase(unittest.TestCase):
  def test_if_method_raises_correct_exception(self):
    test_class = TestClass()
    # note that you dont use () when passing the method to assertRaises
    self.assertRaises(Exception, test_class.raises_exception)

여기에는 많은 답이 있습니다. 이 코드는 예외를 생성하는 방법, 방법에서 예외를 사용할 수있는 방법, 마지막으로 유닛 테스트에서 올바른 예외를 제기하는 방법을 보여줍니다.

import unittest

class DeviceException(Exception):
    def __init__(self, msg, code):
        self.msg = msg
        self.code = code
    def __str__(self):
        return repr("Error {}: {}".format(self.code, self.msg))

class MyDevice(object):
    def __init__(self):
        self.name = 'DefaultName'

    def setParameter(self, param, value):
        if isinstance(value, str):
            setattr(self, param , value)
        else:
            raise DeviceException('Incorrect type of argument passed. Name expects a string', 100001)

    def getParameter(self, param):
        return getattr(self, param)

class TestMyDevice(unittest.TestCase):

    def setUp(self):
        self.dev1 = MyDevice()

    def tearDown(self):
        del self.dev1

    def test_name(self):
        """ Test for valid input for name parameter """

        self.dev1.setParameter('name', 'MyDevice')
        name = self.dev1.getParameter('name')
        self.assertEqual(name, 'MyDevice')

    def test_invalid_name(self):
        """ Test to check if error is raised if invalid type of input is provided """

        self.assertRaises(DeviceException, self.dev1.setParameter, 'name', 1234)

    def test_exception_message(self):
        """ Test to check if correct exception message and code is raised when incorrect value is passed """

        with self.assertRaises(DeviceException) as cm:
            self.dev1.setParameter('name', 1234)
        self.assertEqual(cm.exception.msg, 'Incorrect type of argument passed. Name expects a string', 'mismatch in expected error message')
        self.assertEqual(cm.exception.code, 100001, 'mismatch in expected error code')


if __name__ == '__main__':
    unittest.main()
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top