서론: 테스트되지 않은 코드의 도전 과제
구식 시스템에서 작업할 때, 코드에 충분한 유닛 테스트가 없다는 상황에 직면할 수 있습니다. 이는 변경이나 향상이 필요할 때 상당한 장애물이 될 수 있습니다. 테스트가 없으면 수정이 기존 기능을 망가뜨리지 않을 것임을 검증할 수 없습니다. 그렇다면 테스트되지 않은 코드와 테스트할 수 없는 코드를 변경하는 문제를 어떻게 해결할 수 있을까요?
이 블로그 게시물에서는 레거시 코드의 도전 과제를 탐구하고, 이를 테스트하고 리팩토링하기 위한 효과적인 전략을 제공하여 어려운 상황을 관리 가능한 작업으로 전환할 수 있도록 도와드립니다.
문제 이해하기: 왜 레거시 코드는 테스트하기 어려운가?
해결책을 다루기 전에, 일부 코드가 테스트하기 어려운 이유를 이해하는 것이 중요합니다:
- 높은 의존성: 클래스는 종종 유닛 테스트 세트를 복잡하게 만드는 수많은 상호 의존성을 가지고 있습니다.
- 밀접하게 결합된 코드: 관심사의 분리를 따르지 않는 코드는 테스트를 위해 기능을 분리하기 어렵게 만듭니다.
- 안티 패턴: 좋은 소프트웨어 설계를 저해하는 관행은 테스트에 저항하는 코드를 초래할 수 있습니다.
해결책: 테스트되지 않은 코드를 테스트하기 위한 전략
1. 리팩토링으로 시작하기
리팩토링을 자주 수행하면 작업하기 어려운 코드에 대한 테스트 작성을 경감할 수 있습니다. 방법은 다음과 같습니다:
- 가시성 수정: 프라이빗 멤버를 프로텍티드로 변경하세요. 이렇게 하면 테스트용 서브클래스를 생성하여 테스트 목적으로 메서드나 필드를 재정의할 수 있습니다.
예시
생성자에서 데이터베이스의 데이터를 초기화하는 클래스를 가정해 보세요. 이는 유닛 테스트를 거의 불가능하게 만드는 시나리오입니다.
원본 코드:
public class MyClass {
public MyClass() {
// 바람직하지 않은 DB 로직
}
}
리팩토링된 코드:
public class MyClass {
public MyClass() {
loadFromDB();
}
protected void loadFromDB() {
// 바람직하지 않은 DB 로직
}
}
DB 로딩을 loadFromDB
메서드로 격리함으로써, 테스트 시나리오에서 이 메서드를 쉽게 재정의할 수 있게 됩니다.
2. 테스트 래퍼 생성하기
코드를 리팩토링한 후에는 테스트 래퍼를 생성할 수 있습니다:
샘플 테스트 코드
테스트 코드는 다음과 같이 보일 수 있습니다:
public class MyClassTest {
public void testSomething() {
MyClass myClass = new MyClassWrapper();
// 여기에서 assert 로직
}
private static class MyClassWrapper extends MyClass {
@Override
protected void loadFromDB() {
// 테스트를 위한 일부 목(mock) 로직
}
}
}
래퍼를 사용하면 목 로직을 삽입할 수 있어, 실제 데이터베이스 의존성과 테스트를 효과적으로 격리할 수 있습니다.
3. 기존 도구 고려하기
이러한 전략은 매우 효과적일 수 있지만, 현대적인 라이브러리와 도구가 테스트 프로세스를 용이하게 할 수 있다는 것을 잊지 마세요. DBUnit과 같은 프레임워크를 사용하면 데이터베이스 작업을 포함하는 시나리오를 종종 단순화할 수 있습니다.
4. 프레임워크 사용 시 주의사항
접근 수준을 변경함으로써 테스트를 위한 빠른 승리를 얻을 수 있지만, 이는 라이브러리 또는 프레임워크 저자에게 문제가 될 수 있는 내부 작업을 노출시킬 수 있습니다. 절대적으로 필요하지 않는 한 적절한 캡슐화 및 설계 원칙을 유지하도록 하세요.
결론
테스트되지 않았거나 테스트할 수 없는 코드를 테스트하고 리팩토링하는 것은 벅차게 느껴질 수 있지만, 전략적인 수정과 올바른 도구를 사용하면 레거시 시스템을 유지 관리가 가능하고 테스트 친화적인 코드로 변환할 수 있습니다. 리팩토링을 우선시하고, 테스트 래퍼를 생성하며, 사용 가능한 도구를 활용함으로써 개발자로서의 삶을 더 쉽게 만들고 소프트웨어의 회복력을 보장할 수 있습니다.
주요 요점
항상 테스트 가능한 코드 단위를 생성하려고 노력하고, 변경이 기존 기능에 미치는 영향을 염두에 두세요. 즐거운 코딩 되세요!