테스트 코드를 작성하는 이유?
1. 문서화 역할
2. 코드에 결함을 발견하기 위함
3. 리팩토링 시 안정성 확보
4. 테스트 하기 쉬운 코드를 작성하다 보면 더 낮은 결합도를 가진 설계를 얻을 수 있음
TDD
• Test Driven Development (테스트 주도 개발)
• 프로덕션 코드보다 테스트 코드를 먼저 작성하는 개발 방법
• 기능 동작을 검증 (메서드 단위)
BDD
• Behavior Driven Development (행위 주도 개발)
• 행위에 대한 테스트 코드를 작성하는 개발 방법
• 유저 시나리오 동작을 검증 (시나리오 단위)
• 하나의 시나리오는 Given, When, Then 구조를 가짐
1. BDD의 정의
책임 관계자의 관점에서 보는 애플리케이션의 행위(동작) 중 가치있는 기능부터 개발하는 방식
2. BDD의 특징
1) 사용자(고객)에 좀 더 가까운, 고객이 요구하는 고수준의 기능을 우선적으로 고려한다.
2) 무엇을 테스트 할 것인가?
"현재 시스템에 들어 있지 않은 기능 중 가장 먼저 구현되어야 하는 기능은 무엇인가?"
3) 선조건, 동작, 결과를 구분지어 생각하도록 유도
(given/when/then)
비밀번호 유효성 검증기
- 테스트 코드
package org.example;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.assertj.core.api.Assertions.assertThatCode;
public class PasswordValidatorTest {
/*
* 비밀번호 유효성 검증기
- 요구사항
1. 비밀번호는 최소 8자 이상 12자 이하여야 한다.
2. 비밀번호가 8자 미만 또는 12자 초과인 경우 IllegalArgumentException 예외를 발생시킨다.
3. 경계조건에 대해 테스트 코드를 작성해야 한다.
*/
@DisplayName("비밀번호는 최소 8자 이상 12자 이하면 에러가 발생하지 않는다.")
@Test
void validatePasswordTest(){
assertThatCode(()-> PasswordValidator.validate("serverWizard"))
.doesNotThrowAnyException();
}
@DisplayName("비밀번호가 8자 미만 또는 12자 초과하는 경우, IllegalArgumentException 에러가 발생한다.")
@ParameterizedTest
@ValueSource(strings = {"aabbccc", "aabbccddeeffg"})
void validatePasswordTest2(String password){
assertThatCode(()->PasswordValidator.validate(password))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("비밀번호는 최소 8자 이상 12자 이하여야 합니다.");
}
}
- 클래스 구현
package org.example;
public class PasswordValidator {
public static final String WRONG_PASSWORD_LENGTH_EXCEPTION_MESSAGE = "비밀번호는 최소 8자 이상 12자 이하여야 합니다.";
public static void validate(String password) {
int length = password.length();
if (length < 8 || length > 12) {
throw new IllegalArgumentException(WRONG_PASSWORD_LENGTH_EXCEPTION_MESSAGE);
}
}
}
테스트 코드 작성 방법
1. 어노테이션 활용
@DisplayName("테스트 코드 역할 설명")
@Test -> 테스트를 수행할 메소드
@Before : 각 테스트 메소드 수행 전에 호출
@After : 각 테스트 메소드 수행 후에 호출
ex) 8자리, 12자리 패스워드
2. TDD 3원칙
- 원칙 1 ; 실패하는 단위 테스트를 작성할 때까지 프로덕션 코드를 작성하지 않는다.
- 원칙 2 : 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다.
- 원칙 3 : 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다.
3. AssertJ의 활용
import static org.assertj.core.api.Assertions.assertThat;
@DisplayName("비밀번호는 최소 8자 이상 12자 이하면 에러가 발생하지 않는다.")
@Test
void validatePasswordTest(){
assertThatCode(()-> PasswordValidator.validate("serverWizard"))
.doesNotThrowAnyException();
}
- assertThatCode : 예외가 발생하지 않으면 이 메소드는 실패하지 않는다.
TDD 유의사항
- 테스트 케이스는 이름이 중요하다.
- 더 이상 제대로 동작하지 않는 테스트 케이스는 제거한다.
- TDD는 자동화된 테스트를 만드는 것이 최종 목표가 아니다.
- 모든 상황에 대한 테스트 케이스를 만들 필요는 없다.
- 여러 개의 실패하는 테스트 케이스를 한 번에 만들지 않는다.
- 하나의 테스트 케이스는 하나만 테스트하도록 작성한다.
- 전통적인 테스트 기법을 배워두자.
- 테스트 케이스는 최대한 고립시킨다.
(테스트 케이스가 작성되어 있지 않은 다른 모듈 / 데이터베이스 연동 / 외부 시스템 / 콘솔 출력 / 네트워크 등과 서로 영향을 미치지 않도록 한다.)
참고 서적 및 사이트