2 분 소요


TestCode 작성하는 이유

  • 코드에대한 문서화
  • 코드에 대한 결함을 발견하기 위함
  • 리팩토링 시 안정성 확보

TDD란?

  • Test Driven Development
  • 프로덕션 코드보다 테스트코드를 먼저 작성하는 개발 방법
  • TFD(Test First Development) + Refactoring
  • 기능 동작을 먼저 검증 (메소드 단위)

BDD도 있던데?

  • Behavior Driven Development
  • 시나리오 기반으로 테스트코드를 작성하는 방법
  • 하나의 시나리오는 Given / When / Then 구조

비밀번호 유효성 검증기

요구사항 및 기능명세

  • 비밀번호는 최소 9자 이상 15자 이하
  • 비밀번호가 9자 미만 또는 15자 초과인경우 Exception ㅂ라생
  • 경계조건 확인

Dependency

plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0'
    testImplementation 'org.assertj:assertj-core:3.23.1'
}

test {
    useJUnitPlatform()
}

비밀번호 길이 검증 TestCode 작성

테스트 클래스 및 기본 클래스 생성하기

  • 테스트코드의 패키지의 위치와, main 소스의 패키지의 위치가 동일하게 생성되면 좋다
  • 테스트코드에서 요구조건을 먼저 실현하고, 실현한 요구조건에서 실제 코드에 반영되지 않은 부분들을 하나씩 만들어가며 작업
package org.example;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThatCode;

/**
 * 비밀번호는 최소 9자 이상 15자 이하
 * 비밀번호가 9자 미만 또는 15자 초과인경우 Exception ㅂ라생
 * 경계조건 확인
 */
public class PasswordValidatorTest {

    @DisplayName("비밀번호가 최소 9자 이상 15자 이하면 정상") // 테스트 의도
    @Test
    void validatePasswordTest() {
        assertThatCode(() -> PasswordValidator.validate("123456789"))
                .doesNotThrowAnyException();
    }
}
  • 작성 한 후, PasswordValidator 클래스에 붉은줄이 생성됨
  • PasswordValidator를 main source에 생성
  • PasswordValidator 클래스에 validate 메소드를 생성
      package org.example;
      public class PasswordValidator {
          public static void validate(String password) {
          }
      }
    
  • 테스트 진행 -> 성공

생성 된 클래스들을 Refactoring 하여 상세조건 반영하기

  • 입력된 문자열이 9자 이상 15자 이하인지 확인하고, 아니라면 Exception 발생 코드 작성
package org.example;

public class PasswordValidator {

    public static final String WRONG_PASSWORD_LENGTH_EXCEPTION_MESSAGE = "비밀번호는 최소 9자 이상 15자 이하입니다.";

    public static void validate(String password) {
        int length = password.length();

        if (length < 9 || length > 15) {
            throw new IllegalArgumentException(WRONG_PASSWORD_LENGTH_EXCEPTION_MESSAGE);
        }

    }
}
  • 테스트실행 -> 성공

비밀번호가 9자 미만인 경우 테스트

  • 위와 같은방법으로, TestCode에서 먼저 시도하고 실제 코드에 하나씩 반영하는 방법
  • 이미 Exception 관련 내용을 작성했기 때문에 크게 수정 할 내용이 없다 조건만 테스트
public class PasswordValidatorTest {
    @DisplayName("비밀번호가 9자 미만인 경우 Exception 발생")
    @Test
    void validatePasswordShortExceptionTest() {
        assertThatCode(() -> PasswordValidator.validate("1234"))
                .isInstanceOf(IllegalArgumentException.class)
                .hasMessageContaining(PasswordValidator.WRONG_PASSWORD_LENGTH_EXCEPTION_MESSAGE);
    }
}

비밀번호가 15자 초과인 경우 테스트

  • 위와 같은방법으로, TestCode에서 먼저 시도하고 실제 코드에 하나씩 반영하는 방법
  • 이미 Exception 관련 내용을 작성했기 때문에 크게 수정 할 내용이 없다 조건만 테스트

public class PasswordValidatorTest {
    @DisplayName("비밀번호가 15자 초과인 경우 Exception 발생")
    @Test
    void validatePasswordLongExceptionTest() {
        assertThatCode(() -> PasswordValidator.validate("1234512345123456"))
                .isInstanceOf(IllegalArgumentException.class)
                .hasMessageContaining(PasswordValidator.WRONG_PASSWORD_LENGTH_EXCEPTION_MESSAGE);
    }
}

경계조건에 대한 테스트

  • 우리의 요구조건에 부합하는 비밀번호의 길이는 9자 이상 15자 이하이다.
  • 위의 조건에대한 경계값은 비밀번호가 8자, 혹은 16자 일 경우이다
  • 경계값에 대한 테스트를 추가 해 주면 좋은 테스트를 작성할 수 있다.
  • @Parameterize 를 추가하여 테스트 해 보자

Dependency 추가

testImplementation 'org.junit.jupiter:junit-jupiter-params:5.9.0'

Parameterize를 이용한 테스트

public class PasswordValidatorTest {

    @DisplayName("경계조건에 대해 테스트")
    @ParameterizedTest
    @ValueSource(strings = {"12345678", "1234567890123456"})
    void validatePasswordBoundaryTest(String password) {
        assertThatCode(() -> PasswordValidator.validate(password))
                .isInstanceOf(IllegalArgumentException.class)
                .hasMessageContaining(PasswordValidator.WRONG_PASSWORD_LENGTH_EXCEPTION_MESSAGE);

    }

}
  • ValueSource 내에 들어가있는 값들을 자동으로 바꿔가며 실행시켜 준다
  • ValueSource 내에 선언된 데이터를 함수에서 하나씩 받아 줄 수 있다
  • 실행을 해 보면, 다른 테스트와는 다르게 테스트가 두번 돌아간다

결과화면

테스트결과화면

댓글남기기