티스토리 뷰

IT/SW Dev Methodology

✅ 테스트 전략과 TDD 완전 정복 - 테스트는 왜, 어떻게, 무엇부터 할 것인가?

Stv 2025. 5. 26. 19:12

목차


    시스템이 커질수록, 기능이 많아질수록 중요한 건 "내가 만든 기능이 제대로 동작하는가?", 그리고 "이전 기능을 깨뜨리지 않았는가?"라는 확신이다. 이 확신을 만들어주는 것이 바로 테스트 코드이고, 이걸 개발의 중심에 두는 방식이 TDD(Test-Driven Development)다.


    1️⃣ TDD란 무엇인가?

    TDD는 말 그대로 테스트를 먼저 작성하고 그 다음 코드를 구현하는 개발 방법론이다. 전통적인 개발 흐름과는 순서가 정반대이다.

    📌 TDD 개발 순서 (Red -> Green -> Refactor)

    1. Red - 실패하는 테스트 작성
    2. Green - 테스트가 통과하도록 최소한의 코드 작성
    3. Refactor - 중복 제거, 구조 개선

    이 과정을 끊임없이 반복하며 안정적인 기능 개발을 이어나가는 방식이다.


    2️⃣ TDD를 왜 사용하는가?

    ✅ 안정성

    • 코드 수정 시 기존 기능이 깨지는 것을 즉시 감지 가능

    ✅ 설계 개선

    • 테스트를 먼저 작성함으로써 자연스럽게 SOLID 원칙에 맞는 구조로 개발됨

    ✅ 문서화 효과

    • 테스트 코드는 곧 시스템 사용법에 대한 명세가 된다.

    ✅ 리팩토링의 자유

    • 테스트가 보호막이 되기 때문에, 구조 변경 시 부담이 없음

    3️⃣ 테스트의 종류 정리

    TDD만 알고 테스트 전체를 이해했다고 말할 수 없다. 실제 시스템에서는 여러 레벨의 테스트가 함께 사용되어야 한다.

    테스트 레벨 설명 도구 예시
    단위 테스트 (Unit Test) 메서드/클래스 단위 기능 테스트 JUnit, Mockito
    통합 테스트 (Intergration Test) 컴포넌트 간 상호작용 테스트 SpringBootTest
    인수 테스트 (Acceptance Test) 사용자 시나리오 기반 전체 흐름 테스트 RestAssured, Cucumber
    E2E 테스트 (End-to-End) 브라우저, UI까지 포함한 실제 환경 테스트 Selenium, Cypress

    4️⃣ 실무에서의 테스트 전략

    실무에서는 "모든 테스트를 다 해라"는 이상적 접근보다, 리스크에 맞춰 테스트를 배분하는 전략이 중요하다.

     

    ✅ 핵심 전략 키워드 : 테스트 피라미드

        🔻 UI/E2E 테스트 (적게)
       🔻 통합 테스트 (보통)
      🔻 단위 테스트 (많이)
    • 단위 테스트는 빠르고 변경에 민감하지 않기 때문에 많이 작성
    • 통합 테스트는 복잡한 상호작용 중심
    • UI 테스트는 유지보수가 어렵기 때문에 필요 최소한만 작성

    5️⃣ 테스트 작성 시 유의사항

     

    1. 단위 테스트는 진짜 "단위"만 테스트하자

    • 외부 의존성(Mock)을 제거하고, 로직 자체만 검증

    2. 테스트는 읽기 쉬운 문서처럼

    • 메서드명 : given_조건_when_행동_then_결과() 패턴 사용
    • 테스트 코드 자체가 시나리오 설명이 되어야 함

    3. Mocking은 반드시 필요한 경우에만

    • 과도한 Mocking은 오히려 테스트 신뢰도를 떨어뜨림
    • 서비스 레이어는 Mock, 도메인 로직은 실제 객체 사용 권장

    4. 데이터 상태 명확하게 관리

    • @BeforEach, @AfterEach로 테스트 격리 보장

    6️⃣ TDD 실무 예시 (Java + JUnit + Mockito)

    @Test
    void givenOrderItems_whenCalculateTotal_thenReturnsCorrectSum() {
        // given
        Order order = new Order();
        order.addItem(new OrderItem("상품A", 10000, 2)); // 2개
        order.addItem(new OrderItem("상품B", 5000, 1));  // 1개
    
        // when
        int totalPrice = order.calculateTotal();
    
        // then
        assertEquals(25000, totalPrice);
    }

    이런 테스트를 먼저 작성하고, 실제 calculateTotal() 구현은 나중에 작성한다면 -> TDD 방식


    7️⃣ 테스트와 CI/CD, 품질 지표 연계

    테스트 코드는 단순힌 "잘 되네!" 확인용으로 끝나지 않는다. 최근에는 CI 파이프라인과 연계되어 품질 자동 검증이 이루어진다.

    • GitHub Actions / Jenkins / GitLab CI 등으로 Pull Request 마다 테스트 자동 실행
    • 코드 커버리지 분석 도구 (JaCoCo, SonarQube 등)로 품질 지표 관리
    • 테스트 실패 시 머지 차단 -> 품질 기준 유지

    ✅ 마무리 요약

    항목 핵심 정리
    TDD 테스트 -> 코드 -> 리팩터링 순의 반복 개발
    테스트 전략 단위 > 통합 > UI순의 피라미드 구조
    실무 적용 비즈니스 로직은 TDD, 외부 의존은 통합 테스트
    자동화 CI 파이프라인에 테스트 포함, 커버리지 지표 활용