테스트 상속의 숨은 비용
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
개발 툴
대상자
- 소프트웨어 개발자, QA 엔지니어
- 파이썬 unittest 프레임워크 사용자
- 테스트 코드 유지보수에 관심 있는 개발자
- 난이도: 중간 (테스트 설계 패턴 이해 필요)
핵심 요약
- 테스트 상속 패턴은 유지보수성과 디버깅 편의성을 상실하게 만든다
del BaseAnimalTests
로 인해 테스트 메서드 위치 추적 불가능super().test_speak()
로 인한 복잡한 디버깅 프로세스- 파이썬
pytest.mark.parametrize
가 테스트 재사용성과 가독성을 동시에 제공 @pytest.mark.parametrize('animal_class', [Armadillo, Okapi])
사용 예시- DRY 원칙은 테스트에서는 가독성과 명확성보다 우선시 되어야 한다
섹션별 세부 요약
1. 테스트 상속 패턴의 문제점
- 코드 중복 감소는 유지보수성 저하로 이어짐
BaseAnimalTests
삭제 후 테스트 메서드 추적 불가- IDE에서
test_speak
메서드 검색 실패 - CI 환경에서의 오류 추적 어려움
AssertionError: 0 not greater than 0
발생 시 원인 파악 불가Search everywhere
기능으로도 테스트 위치 찾기 어려움
2. 대안 패턴: `pytest.mark.parametrize`
- 동일한 테스트 로직을 파라미터로 재사용 가능
- ```python
@pytest.mark.parametrize('animal_class', [Armadillo, Okapi])
def test_speak(animal_class):
sound = animal_class().speak()
assert isinstance(sound, str)
assert len(sound) > 0
```
- 테스트 결과 명확성 향상
test_speak[Armadillo] FAILED
/test_speak[Okapi] PASSED
- 실패한 테스트만 재실행 가능
3. `parameterized_class` 사용 예시
parameterized
라이브러리 활용
```python
from parameterized import parameterized_class
@parameterized_class([{'animal_class': Armadillo}, {'animal_class': Okapi}], class_name_func=get_class_name)
class AnimalTests(TestCase):
def test_speak(self):
sound = self.animal_class().speak()
self.assertIsInstance(sound, str)
self.assertGreater(len(sound), 0)
```
- 단점
- IDE 지원 부족
class_name_func
커스터마이징 필요
결론
- 테스트 코드는 가독성과 디버깅 편의성을 위해
pytest.mark.parametrize
와 같은 명시적 방법을 사용해야 한다 - 테스트 상속 패턴은 유지보수성과 명확성 희생으로 비용이 더 크다
- DRY 원칙은 테스트 코드에서는 가독성과 명확성보다 우선시 되어야 한다