Python 함수가 예외를 발생시키는지 테스트하는 방법
assertRaises 사용:
unittest
모듈에서 제공하는 assertRaises
함수를 사용하는 것이 가장 일반적인 방법입니다. 이 함수는 예상되는 예외 유형과 테스트 코드 블록을 매개변수로 취합니다. 예외가 발생하지 않으면 AssertionError
가 발생합니다.
from unittest import TestCase
def my_function(x):
if x == 0:
raise ZeroDivisionError
class MyTest(TestCase):
def test_zero_division_error(self):
with self.assertRaises(ZeroDivisionError):
my_function(0)
try-except 사용:
try-except
블록을 사용하여 예외를 직접 처리할 수도 있습니다. 예상되는 예외 유형이 있는지 확인하고 예외가 발생하지 않으면 AssertionError
를 발생시킵니다.
from unittest import TestCase
def my_function(x):
if x == 0:
raise ZeroDivisionError
class MyTest(TestCase):
def test_zero_division_error(self):
try:
my_function(0)
except ZeroDivisionError:
pass
else:
self.fail("예외가 발생하지 않았습니다.")
contextlib.ExitStack 사용:
contextlib
모듈에서 제공하는 ExitStack
컨텍스트 관리자를 사용하여 여러 예외를 처리할 수 있습니다. 이를 사용하면 예외가 발생하더라도 리소스가 정리되도록 할 수 있습니다.
from unittest import TestCase
from contextlib import ExitStack
def my_function(x):
if x == 0:
raise ZeroDivisionError
resource = open("myfile.txt")
yield resource
class MyTest(TestCase):
def test_zero_division_error(self):
with ExitStack() as stack:
resource = stack.enter_context(my_function(0))
with self.assertRaises(ZeroDivisionError):
pass
위에 제시된 방법 외에도 Python 함수가 예외를 발생시키는지 테스트하는 데 사용할 수 있는 다른 방법들이 있습니다. 사용하는 방법은 테스트하려는 특정 상황에 따라 다릅니다.
참고:
- 단위 테스트에서 예외를 테스트할 때 테스트 코드가 테스트対象 코드를 실제로 실행하지 않도록 주의해야 합니다. 이는 모의 객체 또는 다른 스터빙 기술을 사용하여 수행할 수 있습니다.
- 테스트 코드는 명확하고 간결하게 작성되어야 합니다. 다른 개발자가 쉽게 이해할 수 있어야 합니다.
예제 코드: 다양한 예외 처리 방법
assertRaises 사용
from unittest import TestCase
def my_function(x):
if x == 0:
raise ZeroDivisionError
class MyTest(TestCase):
def test_zero_division_error(self):
with self.assertRaises(ZeroDivisionError):
my_function(0)
설명:
MyTest
클래스는TestCase
클래스를 상속받습니다.test_zero_division_error
메서드는 테스트 케이스입니다.with self.assertRaises(ZeroDivisionError):
문은my_function(0)
를 실행할 때ZeroDivisionError
예외가 발생해야 한다는 것을 예상합니다.- 예외가 발생하지 않으면
AssertionError
가 발생합니다.
try-except 사용
from unittest import TestCase
def my_function(x):
if x == 0:
raise ZeroDivisionError
class MyTest(TestCase):
def test_zero_division_error(self):
try:
my_function(0)
except ZeroDivisionError:
pass
else:
self.fail("예외가 발생하지 않았습니다.")
try-except
블록은my_function(0)
를 실행합니다.ZeroDivisionError
예외가 발생하면 예외가 무시됩니다.
contextlib.ExitStack 사용
from unittest import TestCase
from contextlib import ExitStack
def my_function(x):
if x == 0:
raise ZeroDivisionError
resource = open("myfile.txt")
yield resource
class MyTest(TestCase):
def test_zero_division_error(self):
with ExitStack() as stack:
resource = stack.enter_context(my_function(0))
with self.assertRaises(ZeroDivisionError):
pass
with ExitStack() as stack:
문은 컨텍스트 관리자를 만듭니다.stack.enter_context(my_function(0))
문은my_function(0)
를 실행하고 리소스를 컨텍스트 관리자 스택에 저장합니다.
이 세 가지 예제 코드는 모두 동일한 테스트를 수행하지만 서로 다른 방법으로 구현됩니다. 사용하는 방법은 개인의 선호와 테스트 상황에 따라 다릅니다.
추가 예제
다음은 다른 유형의 예외를 처리하는 방법을 보여주는 몇 가지 추가 예제입니다.
- 특정 예외 메시지 확인:
from unittest import TestCase
def my_function(x):
if x == 0:
raise ValueError("나눌 수 없습니다.")
class MyTest(TestCase):
def test_value_error(self):
with self.assertRaises(ValueError) as error:
my_function(0)
self.assertEqual(error.args[0], "나눌 수 없습니다.")
- 여러 예외 예상:
from unittest import TestCase
def my_function(x):
if x == 0:
raise ZeroDivisionError
elif x < 0:
raise ValueError("음수는 허용되지 않습니다.")
class MyTest(TestCase):
def test_exceptions(self):
with self.assertRaises((ZeroDivisionError, ValueError)):
my_function(0)
- 예외가 발생하지 않은지 확인:
from unittest import TestCase
def my_function(x):
if x > 0:
return x * 2
class MyTest(TestCase):
def test_no_exception(self):
self.assertEqual(my_function(1), 2)
self.assertRaises(TypeError, my_function, "문자열")
단위 테스트에서 예외를 테스트하는 대체 방법
try-except
블록 사용
하지만 이 외에도 상황에 따라 더 유용할 수 있는 몇 가지 대체 방법이 있습니다.
커스텀 예외 클래스 사용:
- 테스트対象 코드에서 발생하는 특정 예외를 나타내는 커스텀 예외 클래스를 만들 수 있습니다.
- 이를 통해 테스트 코드에서 예상되는 예외 유형을 더욱 명확하게 식별할 수 있습니다.
- 예를 들어 다음과 같이
MyCustomError
라는 예외 클래스를 만들 수 있습니다.
class MyCustomError(Exception):
pass
- 테스트 코드에서 다음과 같이
assertRaises
와 함께 사용할 수 있습니다.
from unittest import TestCase
from my_module import MyCustomError
def my_function(x):
if x == 0:
raise MyCustomError
class MyTest(TestCase):
def test_my_custom_error(self):
with self.assertRaises(MyCustomError):
my_function(0)
파이썬 logging 모듈 사용:
logging
모듈을 사용하여 예외 발생 시 로그 메시지를 기록할 수 있습니다.- 이는 테스트 실패의 원인을 디버깅하는 데 도움이 될 수 있습니다.
- 다음과 같이
logging
을 사용하여 예외 메시지를 기록할 수 있습니다.
import logging
def my_function(x):
if x == 0:
logging.error("나눌 수 없습니다.")
raise ZeroDivisionError
class MyTest(TestCase):
def test_zero_division_error(self):
with self.assertRaises(ZeroDivisionError):
my_function(0)
self.assertTrue(logging.error.called)
테스트 커버리지 도구 사용:
pytest-cov
와 같은 테스트 커버리지 도구를 사용하여 테스트 코드가 예외 처리 코드를 얼마나 잘 포함하는지 확인할 수 있습니다.
python unit-testing exception