Hyun's Wonderwall

[Spring Boot] TDD, 단위 테스트, JUnit 본문

Study/Java, Spring

[Spring Boot] TDD, 단위 테스트, JUnit

Hyun_! 2024. 10. 6. 19:50

TDD, 단위 테스트 

TDD: 테스트 주도 개발 (Test-Driven Development)

작은 단위의 테스트 케이스를 작성하고 이를 통과하는 구현 코드를 추가하는 단계를 반복.

 

TDD의 절차

  1. 실패하는 테스트 코드 작성
  2. 테스트를 통과하는 프로그램 작성 (테스트를 통과하는 최소한의 간단한 코드)
  3. 코드 리팩토링

단위 테스트: 하나의 모듈(기능/메서드)을 기준으로 독립적으로 진행되는, 최소 단위의 테스트.

 

단위 테스트 예시

  1. 구현할 기능의 테스트코드를 작성
  2. 단위 테스트를 통과하기 위한 코드를 작성
  3. 테스트 통과 확인(=기능 구현 완료). 이후 리팩토링을 진행한다.

TDD의 Given-When-Then (주석으로 표시하고는 함)

  • Given : 테스트를 위해 필요한 상황 준비
  • When : 테스트하는 메서드 실행
  • Then : 테스트 결과 검증

JUnit5 : 자바 기반 테스팅 프레임워크

  • Platform : JVM에서 테스트 프레임워크를 실행하는 데 기초 제공
  • Jupiter : 테스트를 작성하고 확장하기 위한 프로그래밍 모델과 확장 모델의 조합
  • Vintage : 하위 호환성을 위해 JUnit3과 JUnit4를 기반으로 돌아가는 플랫폼에 테스트엔진을 제공

JUnit5 기본 애노테이션

@Test : 테스트 메서드로 인식, 테스트 진행

- @RepeatedTest, @ParameterizedTest, @TestFactory도 테스트 메서드들

 

@BeforeAll : 전체 테스트가 시작하기 전 단 1번 실행

@AfterAll : 전체 테스트가 완전히 끝난 후 단 1번 실행

 

@BeforeEach : 각 테스트 메서드가 실행될 때마다 그 전에 실행되어야 하는 메서드 명시

- 주로 객체 초기화, 리소스 준비 등에 사용됨

@AfterEach : 각 테스트 메서드가 실행된 후마다 실행

 

@Disabled : 테스트 클래스나 메서드의 테스트 비활성화 (@Test 가 붙은 곳에 붙여서 비활성화할 수 있는 것)

 

JUnit5 테스트 이름 표시하기

@DisplayName : 테스트 결과에 나오는 테스트 클래스와 테스트 메서드 이름을 정할 수 있는 애노테이션

- 테스트 메서드의 이름은 테스트를 할 메서드 이름으로 간단하게 지어서, @DisplayName("설명")에 구체적인 설명을 담는 경우가 많음

@DisplayNameGeneration : 클래스, 메서드 이름을 지정한 방법으로 자동 변형해 표시하는 애노테이션

ex) @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)


JUnit5 Assertion

- 테스트가 원하는 결과를 제대로 리턴하는지 확인할 때 사용. (문제없이 통과되어야 함)

- assertion 메서드 예

  • assertEquals : 두 값을 비교하여 일치 여부 판단.
  • assertEquals(기대하는 값, 실제 값, option); # option은 실패시 반환할 메시지 설정 가능
  • assertTimeout : 특정 시간 안에 실행이 끝나는지 여부 확인
  • assertTimeoutPreemptively : 지정한 시간 내 끝나지 않으면 바로 종료
  • assertTrue : 조건이 성공이면 True

JUnit5 Assumption

- 특정 조건을 만족하는 경우에 테스트를 실행.

- asumption 메서드 예

  • assumeTrue(boolean assumption) : 조건이 true인 경우 다음 라인의 코드 진행
  • assumingThat(boolean assumption, Executable executable) : 조건이 true인 경우 executable의 lambda 형식의 인스턴스 실행

@Enabled___ 와 @Disabled___ : 조건에 따라 테스트를 실행할 지 결정 (OnOs, OnJre, IfEnvironmentVariable)

 

@EnabledOnOs : 특정 OS에서만 테스트 실행 (ex: @EnabledOnOs(value=OS.WINDOWS))

@DisabledOnOS : 특정 OS에서는 테스트를 실행하지 않음

@EnabledOnJre : 특정 Java version 에서만 테스트 실행 (ex: @EnabledOnOs(value={JRE.JAVA_17}))

@DisabledOnJre : 특정 Java version 에서는 테스트를 실행하지 않음

@EnabledIfEnvironmentVariable(name=" ", match=" ") : name에 환경변수의 키값을 넣어주고 match에는 value값을 넣어주면 특정 환경변수 설정에서만 테스트 진행


JUnit5 테스트 반복하기

@RepeatedTest

@RepeatedTest(name="반복 테스트명", value="반복 횟수")

  • name // 아래의 변수 사용해 각 테스트마다 다른 이름 출력 가능 
    {displayName}: @DisplayName으로 설정한 이름을 출력
    {currentRepetition}: 현재 반복 횟수를 출력
    {totalRepetitions}: 전체 반복 횟수를 출력
  • value: 반복 횟수 설정

+) RepetitionInfo 타입의 인자를 받을 수 있음

 

@ParameterizedTest + @ValueSource

@ParameterizedTest(name="반복 테스트명")

  • name  // 아래의 변수 사용해 각 테스트마다 다른 이름 출력 가능 
    {displayName}: @DisplayName으로 설정한 이름을 출력
    {index}: 현재 반복 횟수를 출력
    {0}, {1}, … : 매개변수로 전달받은 것들 중 해당되는 값

@ValueSource(데이터타입s={값1, 값2, …})

  • @ValueSource로 설정한 값의 개수만큼 반복
  • @ValueSource로 설정한 값을 테스트 메서드의 매개변수로 전달받음

JUnit5 테스트 인스턴스

기본 전략: Junit은 테스트 메서드마다 테스트 인스턴스를 새로 만든다. 테스트 메서드를 독립적으로 실행해 예상치 못한 부작용을 방지하기 위함. JUnit5에서는 전략 변경 가능

 

@TestInstance (value = {LifeCycle})

  • 테스트 인스턴스의 생성 단위를 변경하기 위해 사용하는 어노테이션.
  • value 값: PER_METHOD(메서드 단위) / PER_CLASS(클래스 단위)
  • 경우에 따라, 테스트 간에 공유하는 모든 상태를 @BeforeEach 또는 @AfterEach에서 초기화할 필요
  • @BeforeAll과 @AfterAll을 인스턴스 메서드 또는 인터페이스에 정의한 default 메서드로 정의 가능

JUnit5 테스트 순서

주의: 디폴트 상태로는 테스트 메서드 실행 순서를 추측할 수 없음. 순서를 지정할 필요가 있다면 지정해야.

 

메서드명 사전순으로 실행 (알파벳순)

- @TestMethodOrder(MethodOrderer.MethodName.class)

지정한 @Order 순서로 실행

- @TestMethodOrder(MethodOrderer.OrderAnnotation.class)

- 직접 @Order(1) 과 같이 실행 순서를 기입. @Order로 지정되지 않은 메서드는 Integer.MAX_VALUE 할당.

랜덤 실행

- @TestMethodOrder(MethodOrderer.Random.class)

 

JUnit 5:junit-platform.properties

JUnit 설정 파일로, 클래스 패스 루트에 넣어두면 적용된다.