TDD(Test-Driven Development)

이상억·2024년 11월 26일

cs

목록 보기
3/3

TDD (Test-Driven Development) 란 ?

  • SW 개발 방법론 중 하나로, 테스트를 먼저 작성하고 이를 통과시키기 위해 코드를 작성하는 과정을 반복하는 개발 방식
  • 개발 과정에서의 오류를 사전에 방지하고, 코드의 품질과 유지 보수성을 향상시키는데 큰 도움.

TDD의 핵심 사이클 : Red-Green-Refactor

  • Red-Green-Refactor 라는 3단계를 반복하면서 개발을 진행

Red ( 실패하는 테스트 작성 )

  • 구현할 기능에 대한 테스트 케이스를 먼저 작성.
  • 이 단계에서 테스트는 실패해야 함 ( 아직 기능이 구현되지 않았기 때문 )

Green ( 테스트 통과를 위한 최소한의 코드 작성 )

  • 테스트를 통과시키기 위해 필요한 최소한의 코드를 작성
  • 이 단계에서 코드의 최적화나 리팩터링보다는 테스트 통과에 집중

Refactor ( 코드 리팩터링 )

  • 테스트를 통과하면 , 코드를 정리하고 개선.
  • 리팩터링 후에도 모든 테스트가 통과해야 함

TDD의 장점

1. 높은 코드 품질

  • 테스트를 먼저 작성함으로써 코드의 요구사항이 명확해지고, 코드가 보다 깔끔하고 유지보수하기 쉬워짐.

2. 버그 감소

  • 모든 기능에 대해 테스트를 작성하기 때문에, 버그를 조기에 발견하고 수정할 수 있다.

3.리팩터링 용이

  • 테스트가 이미 존재하므로,코드를 리팩터링할 때 기존 기능이 올바르게 동작하는지 즉시 확인할 수 있음.

4. 요구사항 충족 보장

  • 테스트는 요구사항을 기반으로 작성되므로, 요구사항을 누락하지 않고 구현할 수 있음.

TDD의 단점

1. 시간 소모

  • 초기에는 테스트 작성에 추가적인 시간이 필요할 수 있음.

2. 학습 곡선

  • TDD 방식에 익숙하지 않은 개발자에게는 초기 학습이 필요할 수 있다.

3. 복잡한 테스트 관리

  • 프로젝트가 커질수록 많은 테스트 케이스를 관리해야 하므로, 테스트 관리가 복잡해질 수 있음.

TDD 예제: 콜라츠 추측 구현하기

요구사항

  • solution(int num) 함수는 콜라츠 추측에 따라 num이 1이 될 때까지의 연산 횟수를 반환해야 함. 단, 500번 이상의 반복이 발생하면 -1을 반환해야 함.

1단계: 실패하는 테스트 작성 (Red)

  • 아직 solution 함수가 구현되지 않았기 때문에, 테스트를 먼저 작성하고 이 테스트가 실패하는 것을 확인
import static org.assertj.core.api.Assertions.assertThat;

class SolutionTest {
    @Test
    void testCollatzBasicCase() {
        Solution solution = new Solution();
        assertThat(solution.solution(6)).isEqualTo(8); // 예제 6은 8번 반복
        assertThat(solution.solution(1)).isEqualTo(0); // 1은 반복 없이 바로 0 반환
        assertThat(solution.solution(626331)).isEqualTo(-1); // 500번 초과시 -1
    }
}

실행 결과:

  • solution 함수가 아직 구현되지 않았기 때문에, 모든 테스트가 실패

2단계: 최소한의 코드 작성 (Green)

  • 테스트를 통과시키기 위해, 간단히 solution 함수를 구현
    public int solution(int num) {
        long n = num; // int 대신 long으로 오버플로우 방지
        int count = 0;

        while (n != 1) {
            if (count >= 500) return -1; // 500번 이상 반복 시 종료
            n = (n % 2 == 0) ? n / 2 : n * 3 + 1;
            count++;
        }

        return count;
    }
}
  • 테스트를 실행하면 모든 테스트가 통과

3단계: 리팩터링 (Refactor)

  • 코드를 가독성 좋게 리팩터링
class Solution {
    public int solution(int num) {
        long n = num; // int 대신 long으로 오버플로우 방지
        int count = 0;

        while (n != 1 && count < 500) { // 두 조건을 결합
            n = (n % 2 == 0) ? n / 2 : n * 3 + 1;
            count++;
        }

        return (count == 500) ? -1 : count;
    }
}
  • 리팩터링 후에도 테스트를 실행하여 모든 테스트가 통과함을 확인합니다

TDD와 일반 개발의 차이점

일반 개발TDD
코드 작성 후 테스트 작성테스트 작성 후 코드를 작성
테스트는 추가 작업처럼 여겨짐테스트가 개발 과정의 일부
예상 외 동작 발견이 느림테스트가 예상 외 동작을 조기에 발견
요구사항에서 세부 구현으로 진행테스트를 작성하며 요구사항을 점진적으로 세분화
profile
이상억

0개의 댓글