Test Code 란?
테스트 코드란 개발자들이 작성한 코드나 비즈니스 로직 자체를 테스트 하기 위한 코드 입니다.
테스트 코드를 사용하는 이유는 다양합니다.
- 개발 과정에서 문제를 미리 발견할 수 있다.
- 리팩토링 리스크가 줄어든다.
- 애플리케이션을 가동해서 직접 테스트 하는 것보다 테스트를 빠르게 진행할 수 있다.
- 하나의 명세 문서로 기능을 수행한다.
리팩토링 리스크가 줄어든다.
리팩토링 과정에서 새로운 코드가 추가되면 그 코드와 연관된 코드에게 영향을 줍니다.
테스트 코드가 없다면 수시로 확인해야 하지만 테스트 코드가 있다면 혹시 모를 부작용에 대비할 수 있습니다.
Test Code 활용
테스트 코드를 활용하기 위한 순서는 다음과 같습니다.
- 의존성 추가
- 파일 생성
- 테스트 코드 작성
1. 의존성 추가
테스트 코드를 자주 사용하는 Junit을 추가합니다.
// JUnit 5 의존성 추가
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
2. 파일 생성
test code 파일은 main이 아인 test 디렉토리에서 생성을 합니다.
저는 예시로 CouponService를 테스트하는 CouponServiceTest를 만들었습니다.
3. 테스트 코드 작성
테스크 코드의 작성은 한 메소드만 확인하는 유닛 테스트와 여러 메소드가 얽힌 기능을 테스트하는 통합 테스트가 있습니다.
테스트의 형식은 결과값과 기댓값이 같은지를 비교함으로 나타냅니다.
저는 CouponService에 쿠폰을 등록하는 register 메소드와 쿠폰ID로 조회하는 find 메소드의 테스트 코드를 작성해 보았습니다.
package com.dotd.user.service;
import com.dotd.user.dto.coupon.CouponRegisterRequestDto;
import com.dotd.user.dto.coupon.CouponResponseDto;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime;
import java.time.LocalTime;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest
public class CouponServiceTest {
@Autowired
private CouponService couponService;
@Test
@DisplayName("쿠폰 등록 테스트")
public void register() {
// given
LocalDateTime now = LocalDateTime.now();
LocalDateTime sixDaysLater = now.plusDays(6).with(LocalTime.of(23, 59));
CouponRegisterRequestDto dto = CouponRegisterRequestDto.builder()
.name("브론즈 쿠폰")
.description("브론즈 회원들을 위한 쿠폰")
.discount(10)
.duration(sixDaysLater)
.build();
// when
CouponResponseDto result = couponService.register(dto);
// then
// 실제 값 - 기대 값 을 비교한다.
assertThat(result.getName()).isEqualTo(dto.getName());
assertThat(result.getDescription()).isEqualTo(dto.getDescription());
assertThat(result.getDiscount()).isEqualTo(dto.getDiscount());
assertThat(result.getDuration()).isEqualTo(dto.getDuration());
}
@Test
@DisplayName("쿠폰 하나 조회 테스트")
public void find() {
// Given : 쿠폰 등록
LocalDateTime now = LocalDateTime.now();
LocalDateTime sixDaysLater = now.plusDays(6).with(LocalTime.of(23, 59));
CouponRegisterRequestDto dto = CouponRegisterRequestDto.builder()
.name("브론즈 쿠폰")
.description("브론즈 회원들을 위한 쿠폰")
.discount(10)
.duration(sixDaysLater)
.build();
CouponResponseDto data = couponService.register(dto);
Integer id = data.getId();
// When : 쿠폰 ID로 조회
CouponResponseDto result = couponService.find(id);
// Then : 조회 결과 검증
System.out.println(result.getCreatedAt());
System.out.println(data.getCreatedAt());
assertThat(result.getId()).isEqualTo(data.getId());
assertThat(result.getName()).isEqualTo(data.getName());
assertThat(result.getDescription()).isEqualTo(data.getDescription());
assertThat(result.getDiscount()).isEqualTo(data.getDiscount());
assertThat(result.getDuration()).isEqualTo(data.getDuration());
assertThat(result.getCreatedAt()) .isEqualTo(data.getCreatedAt());
}
}
Given, When, Then
테스트 코드를 작성할 때 Given, When, Then 을 사용합니다.
Given : 테스트를 수행하기 위한 필요한 환경을 설정하는 단계
When : 테스트의 목적을 보여주는 단계. 테스트를 통한 결과값을 가져옵니다.
Then : 테스트의 결과를 검증하는 단계.
각각의 역할을 나누어 테스트 코드가 어떠한 시나리오로 진행되는지 명확하게 해줍니다.
assertThat
assertThat은 테스트 코드에서 사용되는 메소드 중 하나로 주어진 조건을 검증하는데 사용됩니다.
테스트 결과값이 예상한 값과 일치하는지 확인하기 위해 사용합니다.
assert(결과값, 예상값) 형식으로 자주 쓰입니다.
마무리
프로젝트를 진행하면서 매번 애플리케이션을 실행시키기 귀찮아서 편한 방법을 찾다가 테스트 코드를 도입했습니다.
제가 오늘 작성한 것은 기초적인 것일 뿐, 제대로 예외 처리가 작동하는지, 여러 메소드가 엮였을 때 원하는 대로 잘 작동하는지, 테스트 코드를 위해 지원하는 다양한 기능들 공부할게 많이 있습니다.
테스트 코드에 관심을 가지게 되었고 프로젝트를 진행하면서 필요한 테스트 코드가 있다면 학습하고 적용하고 정리글을 올려보겠습니다.
감사합니다.