개발 & 방법론/TDD

JUnit5 알아보기

loop-study 2021. 10. 26. 21:41

인텔리제이를 사용하는 자바 개발자가 90% 이상 사용한다는 JUnit을 간단히 알아보러 한다.

자세한 내용은 공식 가이드를 참고하기 바란다.

 


JUnit 5

JUnit이란?

JUnit은 자바 프로그래밍 언어용 유닛 테스트 프레임워크이다. JUnit은 컴파일 타임에 JAR로서 링크된다. [위키백과]

 

JUnit5 구성요소

Junit5는 3가지로 구성되어 있다.

- JUnit Platform : JVM에서 테스트 프레임워크를 실행하는 기반, 테스트 엔진 API 제공

- JUnit Jupiter : 테스트를 작성하기 위한 프로그래밍 & 익스텐션 모델을 제공

- JUnit Vintage : 이전 버전을 위한 테스트 엔진 제공 (JUnit3 & JUnit4 호환)

 

왜 JUnit5 인가?

JUnit 시리즈 중에서 2017년에 공개된 JUnit5를 사용하는 이유를 한 문장으로 요약하자면

스프링 부트 2.2.x 버전부터는 기본적으로 JUnit5 제공하기 때문이다. 

(JUnit5는 Java8 이상을 지원하고, JUnit4는 Java5 이상 지원)  

 

JUnit5 추가하기

스프링 부트 2.2.x 이상이라면 기본적으로 제공되고 있다.

dependencies {
	implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
	useJUnitPlatform()
}

직접 추가해야한다면 다음과 같이 추가한다.

dependencies {
	testImplementation(platform('org.junit:junit-bom:5.8.1'))
	testImplementation('org.junit.jupiter:junit-jupiter')
}

test {
	useJUnitPlatform()
}

만약에 Maven 이라면 다음과 같이 추가한다.

<dependency> 
    <groupId>org.junit.jupiter</groupId> 
    <artifactId>junit-jupiter-engine</artifactId> 
    <version>5.5.2</version> 
    <scope>test</scope>
</dependency>

JUnit5 Annotations

JUnit에서 제공하는 어노테이션은 클래스나 메소드, 파라미터에 적용이 가능하다.

다양하고 많은 어노테이션이 있으며, 우선 JUnit 핵심 어노테이션을 간단히 알아보자. 

 

Method Annotataions

[테스트 지정]

메서드를 5가지 어노테이션으로 테스트로 지정할 수 있다.  

  @Test   테스트를 뜻한다.
  @ParameterizedTest   매개변수화 된 테스트를 뜻한다.
  @RepeatedTest   반복적인 테스트를 뜻한다.
  @TestFactory   동적 테스트를 뜻한다. 
  @TestTemplate   테스트 케이스에 대한 템플릿을 뜻한다.

 

public class JUnitStartTest {

    private final Calculator calculator = new Calculator();

    @Test
    void addition_01() {
        assertEquals(2, calculator.add(1, 1));
    }

    @ParameterizedTest
    @CsvSource(value = {"1,2,3"}, delimiter = ',')
    void addition_02(int a, int b, int result) {
        assertEquals(result, calculator.add(a, b));
    }
    
    @RepeatedTest(10)
    void loop() {
        
    }
    
    ...
}

[라이프 사이클]

테스트가 실행 전 & 후에 실행할 메서드를 지정할 수 있다.

  @BeforeAll   현재 클래스의 모든 테스트가 실행되기 전에 한번 실행된다.
  @BeforeEach   각각 테스트가 실행 전에 실행한다.
  @AfterEach   각각 테스트가 실행 후에 실행한다.
  @AfterAll   현재 클래스의 모든 테스트가 실행된 후에 한번 실행된다.

 

[시간 제한]

테스트 & 라이프사이클 어노테이션에 같이 사용된다.

  @Timeout   지정된 제한 시간을 초과하면 실패처리한다.  

 

[실행 순서]

테스트 실행 순서를 지정한다.

  @Order   테스트 메서드의 실행 순서를 지정한다.

 

Class Annotataions

[인스턴스 전략]

인스턴스 생성 전략을 지정한다.

(JUnit은 기본적으로 테스트간의 의존성을 없애기 위해 테스트 메서드마다 독립적인 객체로 진행한다. ) 

  @TestInstance   현재 클래스의 모든 테스트가 실행되기 전에 한번 실행된다.

 

[실행 순서]

  @TestMethodOrder   테스트 클래스의 실행 순서를 지정한다.

 

[이름 표기]

@DisplayNameGeneration   테스트 이름을 표기하는 방법을 설정한다.

 

[non-static]

  @Nested   해당 클래스가 non-static 내부 클래스임을 나타낸다. @BeforeAll, @AfterAll을 사용할 수 없다. 

 

[확장]

  @ExtendWith   확장자를 선언적인 등록에 사용된다. 
  @RegisterExtension   프로그래밍으로 확장자를 등록하는데 사용한다. 

 

Class & Method Annotataions

[필터]

  @Tag   테스트 그룹을 만들고 원하는 그룹만 테스트할 수 있다. 

 

[이름 표시]

  @DisplayName   클래스명 & 메서드명 대신 노출한 이름을 지정한다. 

 

[비활성화]

  @Disabled   지정된 클래스, 메서드를 실행하지 않는다.

 

Parameter Annotataions

[임시 디렉토리]

테스트 & 라이프사이클 어노테이션에 같이 사용된다.

  @TempDir   필드 및 파라미터 주입을 통해 임시 디텍토리로 사용된다.

 

매개변수 테스트를 도와주는 Annotataions

@ParameterizedTest를 사용하다보면 다양한 인자값이 필요한데, 이를 지원하는 어노테이션 내역이다.

  @ValueSource   지정된 타입 & 배열 값을 넘겨준다. 
  @NullSource   Null 값을 넘겨준다
  @EmptySource   비어있는 값을 넘겨준다
@NullAndEmptySource   Null과 비어있는 값을 넘겨준다.
  @EnumSource   지정된 Enum을 넘겨준다.
  @MethodSource   지정된 메서드의 반환 값을 넘겨준다. 
  @CvsSource   문자열로 이뤄진 배열 값을 넘긴다. 각 문자열은 특정 구분자로 분리되어 여러 타입으로 넘어온다. 
  @CvsFileSource   지정된 경로의 csv 파일을 읽어 값을 넘긴다.
  @ArgumentSource   커스텀 데이터 값을 주입한다 

Assertions

JUnit의 jupiter는 정적 단언 메서드를 제공한다.

assertEquals(A, B) A와 B가 같은 값인지 확인
assertEquals(A, B, C) A와 B가 같은 값인지 확인한다. C로 오차범위 지정이 가능하다. 
assertNotEquals(A, B) A와 B가 서로 다른 값인지 확인
assertSame(A, B) A와 B가 같은 객체인지 확인한다.
assertTrue(A) A가 True인지 확인
assertFalse(A) A가 False인지 확인
assertNull(A) A가 Null인지 확인
assertNotNull(A) A가 존재하는지 확인
assertAll(executables...) 모든 확인 구문
assertTimeout(duration, executable) 지정된 시간안에 실행이 완료되는지 확인

그 외에도 많은 메서드를 제공한다.

 

작성 방법은 아래와 같이 간단하다. 

import static org.junit.jupiter.api.Assertions.*;

public class JUnitStartTest {

    @Test
    void test_assertEquals_01() {
        String a = "이름";
        String b = "이름";

        assertEquals(a, b);
    }

    @Test
    void test_assertNotEquals_01() {
        String a = "loop";
        String b = "공부";

        assertNotEquals(a, b);
    }

    @Test
    void test_assertEquals_02() {
        int a = 1;
        int b = 2;

        assertEquals(a, b, 1);
    }

    @Test
    void test_assertSame() {
        String a = "study";
        String b = a;

        assertSame(a, b);
    }

    @Test
    void test_assertAll() {
        assertAll(
                () -> assertEquals("study", "study"),
                () -> assertNotEquals("study", "loop"),
                () -> assertNull(null),
                () -> assertTrue(true)
        );
    }
}

검증이 통과된 모습

 

 


JUnit에 내용은 많지만, 간단히 기초적인 내용만 언급하고 넘어간다. 

 

참고자료

https://junit.org/junit5/docs/current/user-guide - 공식가이드
더 자바, 애플리케이션을 테스트하는 다양한 방법 - 인프런, 백기선
https://velog.io/@jaehoonlee/JUnit-5-공식-가이드-문서-정리 - 소프트웨어 개발자 이재훈