함수가 예상 예외를 throw하지 않는 경우에만 실패하는 단위 테스트를 작성하는 방법은 무엇입니까?
답변
다음 과 같이 unittest 모듈에서 TestCase.assertRaises
(또는 TestCase.failUnlessRaises
)를 사용하십시오 .
import mymod
class MyTestCase(unittest.TestCase):
def test1(self):
self.assertRaises(SomeCoolException, mymod.myfunc)
답변
Python 2.7부터 컨텍스트 관리자를 사용하여 실제로 발생한 Exception 객체를 파악할 수 있습니다.
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)
그리고 함수가 인수를받는다면, 다음과 같이 assertRaises에 전달하십시오 :
def test_afunction_throws_exception(self):
self.assertRaises(ExpectedException, afunction, arg1, arg2)
답변
파이썬 함수가 예외를 던지는 지 어떻게 테스트합니까?
함수가 예상 예외를 throw하지 않는 경우에만 실패하는 테스트를 작성하는 방법은 무엇입니까?
짧은 답변:
이 self.assertRaises
메소드를 컨텍스트 관리자로 사용하십시오 .
def test_1_cannot_add_int_and_str(self):
with self.assertRaises(TypeError):
1 + '1'
데모
모범 사례 접근 방식은 Python 셸에서 쉽게 보여줄 수 있습니다.
unittest
라이브러리
Python 2.7 또는 3에서 :
import unittest
Python 2.6에서는 unittest2unittest
라는 2.7 라이브러리 의 백 포트를 설치하고 다음 과 같이 별명을 지정할 수 있습니다 .unittest
import unittest2 as unittest
테스트 예
이제 다음과 같은 Python 유형 안전성 테스트를 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'
결과 를 추가하려고 시도 합니다 TypeError
.
더 자세한 출력을 보려면 다음을 시도하십시오.
unittest.TextTestRunner(verbosity=2).run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))
답변
코드는 다음 패턴을 따라야합니다 (이것은 단위 테스트 모듈 스타일 테스트입니다).
def test_afunction_throws_exception(self):
try:
afunction()
except ExpectedException:
pass
except Exception:
self.fail('unexpected exception raised')
else:
self.fail('ExpectedException not raised')
Python <2.7에서이 구문은 예상되는 예외에서 특정 값을 확인하는 데 유용합니다. unittest 함수 assertRaises
는 예외가 발생했는지 확인합니다.
답변
에서 : http://www.lengrand.fr/2011/12/pythonunittest-assertraises-raises-error/
먼저, dum_function.py 파일에 해당하는 (여전히 d : 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
완벽 해!
… 나도 완벽합니다!
Mr. Julien Lengrand-Lambert 씨 감사합니다
이 테스트 어설 션은 실제로 오 탐지를 반환합니다 . ‘assertRaises’내부의 람다 는 테스트 된 함수가 아닌 형식 오류를 발생시키는 단위이기 때문에 발생 합니다.
답변
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
