테스트를 작성할 때 종종 외부 의존성으로 인해 테스트가 어려워지는 경우가 있습니다. 예를 들어, 데이터베이스나 네트워크와 같은 외부 리소스에 접근하는 테스트의 경우, 실행이 느려질 수 있거나, 예상치 못한 결과를 가져올 수 있습니다. 이러한 문제를 해결하기 위해 unittest 라이브러리는 ‘테스트 더블’을 제공합니다.
테스트 더블은 테스트 동안 원래 객체를 대체하여 외부 의존성을 모방하는 객체입니다. 이를 통해 테스트를 더 쉽게 작성하고, 실행 속도를 높일 수 있습니다. unittest는 다음과 같은 테스트 더블 종류를 제공합니다:
1. Mock
Mock은 새로운 기능을 추가하지 않고 원래 객체를 가짜로 대체하는 가장 간단한 테스트 더블입니다. Mock 객체는 원래 객체의 기능과 상태를 모방하며, 개발자가 원하는 대로 동작하도록 설정할 수 있습니다. 또한, 테스트 도중보다 자세한 정보를 제공하여 테스트가 실패하는 경우 디버깅에도 도움이 됩니다.
from unittest.mock import Mock
# Mock 객체 생성
mock_obj = Mock()
# Mock 객체 설정
mock_obj.some_function.return_value = 42
# 테스트에서 Mock 객체 사용
assert mock_obj.some_function() == 42
2. MagicMock
MagicMock은 Mock의 서브클래스로, 기본적으로 모든 호출을 성공으로 가정하는 특징을 갖습니다. 만약 특정 호출이 예상되는 결과가 없는 경우 그냥 None 값을 반환합니다.
from unittest.mock import MagicMock
# MagicMock 객체 생성
magic_mock_obj = MagicMock()
# MagicMock 객체 설정
magic_mock_obj.some_function.return_value = 10
# 테스트에서 MagicMock 객체 사용
assert magic_mock_obj.some_function() == 10
3. Dummy
Dummy는 실제 결과 값을 제공하지 않고, 다른 객체들이 예상하는 파라미터만 제공하는 테스트 더블입니다. 흔히 인터페이스를 정의할 때 많이 사용됩니다.
class DummyObj:
def some_function(self, param):
pass
# Dummy 객체 생성
dummy_obj = DummyObj()
# 다른 객체에서 Dummy 객체 사용
assert another_obj.some_function(dummy_obj) == None
4. Stub
Stub은 특정 호출에 대해 미리 정의된 결과 값을 반환하는 테스트 더블입니다. 이러한 기능을 사용하여 원하는 결과 값을 테스트에 주입할 수 있습니다.
from unittest.mock import MagicMock
# Stub 객체 생성
stub_obj = MagicMock()
stub_obj.some_function.return_value = 10
# Stub 객체 사용
assert stub_obj.some_function() == 10
위에서 살펴본 테스트 더블들은 unittest 라이브러리에서 제공하는 종류 중 일부입니다. 다양한 테스트 시나리오에 따라 적절한 테스트 더블을 선택하고, 테스트 더블을 적절히 활용하여 외부 의존성을 제어하고 테스트의 신뢰성과 유지보수성을 높일 수 있습니다.