본문 바로가기
Spring/테스트

[테스트 주도 개발 시작하기] Chap04 TDD-기능 명세-설계

by compile-this 2024. 9. 1.

 

기능명세

다양한 형태의 기능명세를 통해 설계를 시작할 수 있다.

기능 명세를 구체화하여 입력과 결과를 도출하고, 코드에 반영하는 과정에서 기능(함수)의 이름, 파라미터, 리턴타입등이 결정된다.

 

 

설계 과정을 지원하는 TDD

TDD를 적용하여 테스트코드를 먼저 작성하기 위해서는 다음 두 가지를 할 수 있어야 한다.

  1. 테스트할 기능을 실행
    테스트할 기능을 실행하기 위해서는 다음 항목을 설계해야 한다.
    • 테스트 대상이 되는 클래스와 메서드
    • 메서드의 인자 타입과 개수
  2. 실행 결과를 검증
    실행 결과를 검증하기 위해서는 다음 항목을 설계해야 한다.
    • 검증하려는 메서드의 리턴값
      • 리턴값이 없다면 메서드의 실행결과를 검증할 수 있는 별도의 메서드 혹은 변수 등

아래 예시를 통해 구체화해 보자.

 

 

테스트 코드를 통한 설계 과정 예시

chap02에서 구현한 암호 강도 검사를 통해 살펴보면 다음 순서와 같다.

 

1. 테스트 대상이 될 클래스의 이름 정하기

// 이름을 선택한 뒤에 해당 이름을 사용한 테스트 클래스 작성
public class PasswordStrengthMeterTest {

}



2. 테스트에서 실행할 메서드 이름, 파라미터 정하기

@Test
void meetsAllCriteria_Then_Strong() {
	PasswordStrength meter = new PasswordStrengthMeter();
    // 테스트 코드에서 실행할 메서드의 이름과 파라미터를 결정
	값 타입 결과 = meter.meter("ab12!@AB");
}

 

 

3. 실행결과를 검증하기 위해 메서드의 리턴값 정하기

@Test
void meetsAllCriteria_Then_Strong() {
    PasswordStrength meter = new PasswordStrengthMeter();
    // 결과를 검증하는 방법을 고민하는 과정에서 리턴 타입을 결정
    PasswordStrength result = meter.meter("ab12!@AB");
    assertEquals(PasswordStrength.STRONG, result);
}

 

 

위 과정을 통해 TDD를 하다 보면 일부 설계를 진행하게 됨을 알 수 있다.

 

 

필요한 만큼 설계하기

이전 chapter에서 살펴봤듯이 TDD는 테스트를 통과할 만큼의 코드를 구현하는 게 규칙이다.

이 규칙에 반하여 미리 예측해서 구현한다고 가정해 보자.

만약 최초의 요구사항이 변경되거나 추가될 때 미리 예측해서 만들어 놓은 코드가 불필요해지거나,
추가해야 될 구현을 방해하게 될 수도
있다.
이와 반대로 TDD는 필요한 만큼 구현하고 설계하기 때문에 불필요한 구현을 덜 하게 되기 때문에 효율적이다.

 

 

기능 명세 구체화

테스트 코드를 작성하려면 입력과 결과가 명확해야 하므로, 기능명세에 모호한 부분이 발생하면
구체적인 예시로 바꾸어 테스트 코드에 반영해야 한다.
이렇게 되면 테스트 코드는 예시를 이용한 구체적인 명세가 된다.

구체적인 예시를 이용해서 테스트 코드를 추가하다 보면 기능 명세를 보다 잘 이해하고 모호함을 없앨 수 있다.

 

 

요약

TDD가 기능명세에 대한 모든 설계를 할 수 있게 하지는 않지만, 설계 과정에 많은 부분 참여함을 알 수 있다.

TDD를 실무에 적용할 수 있는 상태라면, [구현 후 테스트] 보다 [테스트 후 구현]이 더 효율적임을 알 수 있다.

또한 테스트 진행 시 기능명세에 모호한 부분이 있다면 구체적인 예시를 추가하여 모호함을 없앨 수 있다.