[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
null
과 empty
값 모두를 전달하기 위해 사용한다.
@ParameterizedTest
@NullAndEmptySource
void isBlank_ShouldReturnTrueForNullAndEmptyStrings(String input) {
assertTrue(Strings.isBlank(input));
}
➕ null
과 empty
값, 변형된 빈 문자열을 전달하기 위해 @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
클래스 또는 메서드를 비활성화 하는데 사용한다.