[JUnit5] 테스트 작성(1) - 전체적인 틀 + 이름 작성
JAVA/JUnit

[JUnit5] 테스트 작성(1) - 전체적인 틀 + 이름 작성

서론 

개발을 하면서 예상치 못한 곳에서 에러가 발생하거나, 또는 왜 발생하는지를 모르는 경우가 있습니다.

그리고 작은 범위에서는 괜찮다가, 여러 객체들을 사용하면서 오류가 발생하는 경우가 있습니다.

이를 방지하기 위해서 개발자들은 테스트 케이스를 작성하기 시작했고, TDD (테스트 주도 개발)이라는 용어까지 생겨났습니다. 테스트의 열풍이 불기 시작한 것이죠.

 

JUnit 플랫폼은 JVM에서 테스트 프레임워크를 시작하기 위한 기반을 제공합니다.

특히 슬슬 JUnit5가 많이 사용되고 있기 때문에 JUnit5에 대해 공부를 시작하려고 합니다.

 

JUnit3, 4에서 사용하던 Vintage 플랫폼에서 변경된 JUnit Jupiter는 JUnit5의 테스트 및 확장을 작성하기 위한 새로운 프로그래밍 모델과 확장 모델의 조합들입니다.

 

 

1. 전체적인 테스트 틀 작성하기

public class BasicTest {
    @BeforeAll
    static void initAll() {
        System.out.println("=== 테스트 클래스 시작 ===");
    }

    @BeforeEach
    void init() {
        System.out.println("=테스트 메서드 시작=");
    }


    @Test
    void test1() {
        System.out.println("테스트 1 진행");
    }

    @Test
    void 테스트2() {
        System.out.println("테스트 2 진행");
    }

    @DisplayName("테스트3 \uD83D\uDE31")
    @Test
    void test3WithEmoji() {
        System.out.println("테스트 3 진행");
    }

    @Disabled
    @Test
    void disabledTest() {
        System.out.println("테스트 4는 진행하지 않습니다.");
    }
    
    
    @AfterEach
    void tearDown() {
        System.out.println("=테스트 메서드 종료=\n");
    }
    
    @AfterAll
    static void tearDownAll() {
        System.out.println("=== 테스트 클래스 종료 ===");
    }

}

코드를 실행하면 다음과 같은 결과가 발생합니다.

테스트 결과

 

@Test

@Test 어노테이션은 JUnit 프레임워크가 이 메서드가 테스트 전용 메서드임을 알도록 마킹해주는 어노테이션입니다.

각 메서드 위에 @Test를 표기하시면 됩니다.

@Test로 마킹된 메서드들을 테스트 메서드라고 하겠습니다.

 

 

@BeforeAll & AfterAll

만약 테스트 클래스를 시작과 끝마칠때 따로 설정할 것이 있는 경우 사용하는 어노테이션입니다.

이 어노테이션을 사용하면 전체 테스트의 시작(@BeforeAll)과 끝부분(@AfterAll)에 단 한번 실행됩니다.

 

BeforeAll과 AfterAll은 생명주기가 클래스 전체이기 때문에 static를 붙여주어야 합니다.

==실행 예시==
@BeforeAll 실행

테스트 메서드1 실행
테스트 메서드2 실행
...

@AfterAll 실행

(JUnit4의 @BeforeClass가 @BeforeAll로, @AfterClass가 @AfterAll로 변경되었습니다.)

 

 

@BeforeEach & AfterEach

@BeforeAll, @AfterAll이 전체 테스트의 시작과 끝에 실행이 되었다면, @BeforeEach, @AfterEach의 경우에는 각 테스트 메서드 실행 전 후에 한 번씩 실행되도록 하는 어노테이션입니다.

== 실행 예시 ==
@BeforeEach 실행
테스트 메서드1 실행
@AfterEach 실행

@BeforeEach 실행
테스트 메서드2 실행
@AfterEach 실행

...

(JUnit4의 @Before이 @BeforeEach로, @After이 @AfterEach로 변경되었습니다.)

 

 

 

@Disabled

코드를 업데이트하면서 기존 테스트 메서드와 충돌이 발생해 부분적으로 테스트를 비활성화해야 할 때가 있습니다.

이런 경우 @Disabled를 사용하면 해당 테스트 메서드를 비활성화할 수 있습니다.

 

기본적으로는 [메서드 Path + is @Disabled]라는 코멘트를 남깁니다.

 추가적인 코멘트를 넣고 싶을 때는 @Disabled(String value)를 입력하면 됩니다.

@Test
@Disabled
public void disabledTest() {
    NamingAndAnnotation study = new NamingAndAnnotation();
    System.out.println("테스트 1 진행");
    assertNotNull(study);
}
 
@Test
@Disabled("해당 테스트를 실행하지 않습니다.")
public void disabledTest2() {
    NamingAndAnnotation study = new NamingAndAnnotation();
    System.out.println("테스트 2 진행");
    assertNotNull(study);
}

테스트 결과

 

 

 

 

2. 테스트 이름 짓기

총 세 가지 방법으로 표기가 가능합니다.

  • 메서드명으로 표기
  • @DisplayName 어노테이션으로 표기
  • 전체적인 클래스에 규칙을 부여해서 표기.
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
public class NamingTest {

    @Test
    void namingTest1() {

    }

    @Test
    void 테스트는_한글로_표기가_가능합니다() {

    }

    @DisplayName("DisplayName을 사용하면 모든 문자열을 표현이 가능합니다. \uD83D\uDE31")
    @Test
    void testWithEmoji() {

    }
}

테스트 결과

메서드명으로 표기

  • 기본적으로 테스트명은 메서드 이름을 따릅니다.
  • 재밌는 점은 테스트 메서드는 한글로도 표기가 가능하다는 것입니다. 하지만 이런 경우 테스트 메서드를 찾을 때 불편하니 혼자서 토이 프로젝트할 때나 추천합니다.
  • Java 표준 문법에 의해 띄어쓰기가 불가능합니다. 그래서 언더바를 사용합니다.
  • 띄어쓰기를 보고 싶은 경우 @DisplayNameGeneration 어노테이션을 클래스 레벨에 등록하시면 됩니다.

 

 

@DisplayName

  • 전체적인 능률 향상을 위해 테스트를 알아보기 쉽게 만들 필요성이 있습니다. (띄어쓰기나, 통일화)
  • @DisplayName 어노테이션을 사용하면, 문자열로 표기가 가능합니다. (심지어 이모지까지 표기가 가능합니다.)
  • 가장 추천하는 방법입니다.

 

 

@DisplayNameGeneration, @DisplayNameGenerator

  • 메서드명만으로도 충분할 경우 일부분만 고쳐서(대, 소문자, 띄어쓰기 등...) 표기를 하고 싶은 경우가 있습니다.
  • 이런 경우에 클래스 레벨로 이 어노테이션을 등록하면 이 테스트 클래스 전체에 해당 규칙을 지켜 메서드명이 만들어집니다.
DisplayNameGenerator 구현 클래스 설명
Standard 표준 이름 생성동작. '메서드명(파라미터 타입)'으로 표기가 됩니다.
Simple 표준 이름 생성보다 간단하게 후행 괄호를 제거해 표기합니다.
ReplaceUnderscores 언더스코어(_)를 공란으로( )로 변환합니다.
IndicativeSen 이 테스트 메서드를 포함하는 클래스 이름을 연결해서 표기합니다.
'테스트 클래스 이름, 테스트 메서드 이름'
@DisplayName("DisplayNameGenerator의 속성에서")
public class NamingTest {

    @Test
    void 표준방법은_메서드명과_파라미터_타입까지_표기(String name, int number) { }

    @Nested
    @DisplayName("Simple을 사용하면")
    @DisplayNameGeneration(DisplayNameGenerator.Simple.class)
    class UsingSimple {
        @Test
        void 후행괄호를_제거한다() { }
    }

    @Nested
    @DisplayName("ReplaceUnderscores를 사용하면")
    @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
    class UnderscoresToSpace {
        @Test
        void 언더스코어를_띄어쓰기로_변환이_가능하다() { }
    }

    @Nested
    @DisplayName("IndicativeSentences를 사용하면")
    @DisplayNameGeneration(DisplayNameGenerator.IndicativeSentences.class)
    class IndicativeSentences {
        @Test
        void 클래스이름까지_붙여서_표현이_가능하다() { }
    }
}

 

테스트 결과 (테스트 실패는 무시하세요~)

 

 

junit-platform.properties 사용

클래스가 아니라 더 큰 범위로 설정을 원하면 JUnit 전체 설정을 도와주는 해당 프로퍼티를 사용하면 됩니다!

## 테스트 이름 표기 전략 설정 @DisplayNameGeneration
junit.jupiter.displayname.generator.default = \
    org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores

 

다음 장부터는 가장 많이 사용할 Assertions, Assumptions를 사용해봅시다!

 

 

 

참고자료

JUnit 5 User Guide

 

JUnit 5 User Guide

Although the JUnit Jupiter programming model and extension model will not support JUnit 4 features such as Rules and Runners natively, it is not expected that source code maintainers will need to update all of their existing tests, test extensions, and cus

junit.org