본문 바로가기

자바

[JUnit5] 내가 정리한 JUnit5

반응형

2021-02-04 글 

우테코 level1 1주차 - JUnit을 활용한 단위 테스트 이론 및 실습
단위테스트에 대해서 배웠다. 허나 나는 단위 테스트는 처음이라 👀
처음 배운 JUnit5를 익히기 위해 정리해본다.

JUnit이란

  • 자바 프로그래밍 언어를 위한 단위 테스트 프레임 워크
  • xUnit으로 알려진 단위 테스트 프레임 워크 제품군이다.
  • "먼저 테스트 한 다음 코딩"
  • "조금 테스트, 약간 코딩, 약간 테스트, 약간 코딩"

특징

  • 테스트를 작성하고 실행하는 데 사용되는 오픈 소스 프레임 워크
  • annotation을 제공한다.
  • 테스트 기대 결과를 위한 assertion을 제공한다.
  • test runner를 제공한다.
  • 퀄리티를 올리며 빠르게 코드를 작성할 수 있게 해준다.
  • 자동으로 테스트가 실행될 수 있으며 자체의 결과를 확인하고 바로 결과를 제공한다.
  • 테스트 cases 및 기타 테스트 suites를 포함하는 test suites로 구성된다.
  • 테스트 성공시 초록, 실패시 빨강

단위 테스트 케이스는 왜 써?

  • 메소드가 에상대로 동작하는지 확인한다.
  • 원하는 결과를 빠르게 확인하기 위해서는 테스트 프레임 워크가 필요하다.
  • 이 역할을 JUnit이 한다.
  • 알고 있는 입력과 기대하는 출력으로 작성된다.
  • 각 요구 사항에 대해 최소 두 개의 단위 테스트 케이스가 필요하다. (양성, 음성)
  • 요구사항에 하위 요구사항이 있으면 여기에도 두 개의 단위 테스트 케이스가 필요하다.

JUnit5 👀

모듈 구성

JUnit Platform

테스트 프레임워크를 실행하는데 기반이 되는 모듈
플랫폼에서 동작하는 테스트 프레임 워크 개발을 위한 TestEngine API를 정의한다.
command line에서 console Launcher와 JUnit4 기반 환경의 플랫폼에서 실행하기 위한
JUnit 4 based Runner 를 제공한다.
각종 IDE 및 빌드 도구에 존재한다.

JUnit Jupiter

테스트를 위한 새로운 프로그래밍 모델 과 확장 모델의 조합이다.
주피터의 하위 프로젝트는 플랫폼에서 주피터 동작을 위한 TestEngine을 제공한다.

JUnit Vintage

하위 버전을 실행할 수 있는 TestEngine을 제공한다.

Installation

maven이나 gradle 프로젝트에서
Jupiter Engine Dependency and Platform Runner Dependency
즉 최소 2개의 dependency가 필요하다.

maven

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
    <junit.jupiter.version>5.5.2</junit.jupiter.version>
    <junit.platform.version>1.5.2</junit.platform.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>${junit.jupiter.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-runner</artifactId>
        <version>${junit.platform.version}</version>
        <scope>test</scope>
    </dependency>
</dependencies>

gradle

testRuntime("org.junit.jupiter:junit-jupiter-engine:5.5.2")
testRuntime("org.junit.platform:junit-platform-runner:1.5.2")

Java Versions

Java8 이상이어야 한다.

Tests 작성하기

이 부분은 강의 시간에 다뤘던 코드로!

...

public class SetTest {
    private Set<Integer> numbers;

    @Test
    void checkSizeOfSet(){
        assertThat(numbers.size()).isEqualTo(4);
    }

}

Test Class

최소 하나의 테스트 메소드를 포함하는 최상위 클래스
single constructor 여야 한다.

Test Method

@Test, @ParameterizedTest 등의 어노테이션을 통해 테스트 메소드임을 나타낸다.

  • assertJ를 통해 테스트 코드의 가독성을 높이며 에러 메세지를 쉽게 확인할 수 있다.

공부한 Annotation 몇 개

@Test

메서드가 테스트 메서드임을 나타낸다.

@ParameterizedTest

메서드가 매개변수가 있는 테스트임을 나타낸다.

파라미터를 전달하는 방법은 아래의 어노테이션과 더불어 Source로 넘겨준다.

@ValueSource

단일 리터럴 값 배열을 테스트 메서드에 전달할 수 있으며,
매번 테스트 메서드에 하나의 인수 만 전달할 수 있다.
short, byte, int, long, float, double, char, boolean, java.lang.String, java.lang.Class 리터럴 값을 지원한다.

@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void contains1(int i) {
    assertThat(numbers.contains(i)).isTrue();
}

@CsvSource

여러 파라미터를 전달하고자 할 때 사용한다.
주로 입력 값과 기대 값을 함께 전달하며 테스트할 때 사용한다.
,로 값을 구분하지만 delimiter 속성을 사용해 사용자 정의를 할 수 있다.

@ParameterizedTest
@CsvSource(value = {"1:true", "5:false"}, delimiter = ':')
void contains3(int i, boolean expected) {
 assertThat(expected).isEqualTo(numbers.contains(i));
}

@NullSource

단일 null 값을 전달할 수 있다.

하지만 기본 데이터 타입은 null 값을 허용할 수 없어 @NullSource를 사용할 수 없다.

@EmptySource

메서드에 하나의 빈 값을 인수에 전달한다.

@ParameterizedTest
@EmptySource
void isBlank_ShouldReturnTrueForEmptyStrings(String input) {
    assertTrue(Strings.isBlank(input));
}

@NullAndEmptySource

nullempty 값 모두를 전달하기 위해 사용한다.

@ParameterizedTest
@NullAndEmptySource
void isBlank_ShouldReturnTrueForNullAndEmptyStrings(String input) {
    assertTrue(Strings.isBlank(input));
}

nullempty 값, 변형된 빈 문자열을 전달하기 위해 @ValueSource, @NullSource, @EmptySource를 함께 결합해 사용할 수 있다.

@ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = {"  ", "\t", "\n"})
void isBlank_ShouldReturnTrueForAllTypesOfBlankStrings(String input) {
    assertTrue(Strings.isBlank(input));
}

@EnumSource

열거형 갑의 배열을 메서드에 전달한다.

@ParameterizedTest
@EnumSource(Month.class) // 12 months를 전달
void getValueForAMonth_IsAlwaysBetweenOneAndTwelve(Month month) {
    int monthNumber = month.getValue();
    assertTrue(monthNumber >= 1 && monthNumber <= 12);
}

위 예시에서 names 속성을 사용하여 몇 개의 달만 전달할 수도 있다.

@ParameterizedTest
@EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"})
void someMonths_Are30DaysLong(Month month) {
    final boolean isALeapYear = false;
    assertEquals(30, month.length(isALeapYear));
}

@ValueSource 와 비슷하게 테스트 실행 당 하나의 매개변수만 전달할 수 있다.

@BeforeEach / @AfterEach

메서드가 현재 테스트 클래스의 각각의 메서드보다 먼저 / 각각의 메서드의 이후에 실행한다.

  • 리턴 타입 : void
  • private 불가능
  • static 불가능
    @BeforeEach
    void setUp(){
      numbers = new HashSet<>();
      numbers.add(1);
      numbers.add(2);
      numbers.add(3);
      numbers.add(4);
    }

@BeforeAll / @AfterAll

메서드가 현재 테스트 클래스의 모든 메서드보다 먼저 / 모든 메서드의 이후에 실행한다.

@DisplayName

클래스 또는 메서드에 대한 사용자 지정 표시 이름을 선언하는데 사용한다.

@DisplayName("Set의 사이즈 확인 테스트")
@Test
void checkSizeOfSet(){
    assertThat(numbers.size()).isEqualTo(4);
}

@Disabled

클래스 또는 메서드를 비활성화 하는데 사용한다.

참고 자료

반응형