답변.
레거시 코드의 자동화 테스트는 IT 분야에서 가장 큰 고전적인 문제 중 하나입니다.
문제의 역사: 많은 기업들이 미래의 자동화를 고려하지 않고 작성된 시스템을 테스트해야 할 필요성을 겪고 있습니다. 종종 이러한 프로젝트는 문서화가 부족하고, 기술 부채가 많으며, 격리된 구성 요소가 부족합니다.
문제: 주요 어려움은 다음과 같습니다.
- 테스트 훅 및 통합 지점의 부족
- 테스트를 위한 데이터 격리 불가능
- 모듈 간 강한 상호 의존성
- 코드에 반영되지 않은 많은 수의 비정상 및 변경 사항들
해결책: 일반적으로 프로세스는 단계적으로 진행됩니다:
- 시스템 분석: 핵심 비즈니스 프로세스를 정의하고 자동 테스트의 커버리지 영역을 조정해야 합니다.
- 테스트 지점 구현: 가능한 범위 내에서 일부 코드를 프록시로 감싸거나 테스트 더블에 맞게 조정하거나 의존성 주입 패턴을 사용합니다.
- 단계별 자동 테스트 커버리지 준수: 가장 "단순한" 코드 및 가장 적게 연결된 코드의 테스트부터 작성합니다.
- 지속적인 지원 및 리팩토링: 테스트를 추가한 후 개선을 위한 안전그물이 되도록 사용합니다.
주요 특징:
- 테스트는 종종 처음부터 작성되는 것이 아니라 기존 함수에 대한 "래퍼"에서 시작됩니다.
- 아키텍처에 테스트 가능성을 단계적으로 추가해야 합니다.
- 비즈니스는 핵심 시나리오의 규정에 최대한 관여해야 합니다.
함정 질문들.
전체 레거시 코드의 리팩토링을 완료하기 전에 자동 테스트를 작성할 수 있나요?
네, 자동 테스트는 리팩토링을 안전하게 하기 위해 필요합니다. 완전한 "완벽함"을 기다려서는 안 되며, 반대로 테스트는 과감한 변화를 돕습니다.
모든 레거시 코드를 자동 테스트로 완전히 커버하려고 시도하는 것이 좋습니까?
아니요. 가장 위험하고 자주 사용되는 시나리오에 집중해야 합니다. "모든 것을 커버"하는 것은 속도를 해치며 의미가 없습니다.
레거시 코드를 테스트하기 위해 현대적인 패턴(DI 등)을 도입해야 합니까?
아니요, 하지만 리소스가 허용된다면 사용하는 것이 좋습니다. 첫 번째 단계는 최소한의 격리, 모의(mock) 및 코드 내 특별 테스트 지점입니다.
일반적인 실수 및 안티 패턴
- 모든 코드를 한 번에 자동 테스트에 맞추려는 시도 — 프로젝트가 중단되고 비즈니스 의미를 잃습니다.
- 미미한 기능에 대한 "편집증적" 커버리지.
- 개발, 테스트 및 비즈니스 간의 통신 부족.
실생활 사례
부정적 케이스
팀은 레거시 코드를 SOLID 패턴에 따라 재작성하고 100% 코드를 테스트로 커버하려고 했습니다.
장점:
- 아키텍처의 기본 개선.
- 장기적으로 테스트가 도움이 될 수 있습니다.
단점:
- 몇 달 간 개발이 지연됩니다.
- 비즈니스 요구 사항과의 지속적인 버그와 동기 불일치.
- 테스트가 작성될 시점에 코드의 актуальность 상실.
긍정적 케이스
특정 주요 계산 지점에 대해서만 자동 테스트를 도입하고, 일반 코드를 최소한으로 변경하면서 특별한 스텁을 도입했습니다.
장점:
- 프로젝트의 최소한의 지연.
- 수정 시 신뢰성 향상.
- 작업 진행에 따라 커버리지를 확장할 수 있는 가능성.
단점:
- 비표준 접근 방식을 문서화하는 것이 어렵습니다.
- 여전히 일부 코드가 커버되지 않은 채로 남아 있습니다.