테스트는 TDD와 단위 테스트(Unit Test)로 나눌 수 있다.
테스트가 주도하는 개발을 의미한다.
테스트 코드를 작성 후 테스트가 통과하면 코드에 참여시킨다
TDD의 첫 번째 단계인 기능 단위의 테스트 코드를 작성하는 것.
TDD와 달리 테스트 코드를 먼저 작성할 필요도, 리펙토링도 포함되지도 않는다.
오늘 작성할 내용은 단위테스트에 관한 것이다.
기본 구조
//예시
import org.junit.jupiter.api.Test;
public class Example {
@Test
void test() {
//given
//when
//then }}
Junit5 어노테이션 | 설명 |
---|---|
@Test | 테스트 Method임을 선언 / 정적 테스트 |
@ParameterizedTest | 매개변수를 받는 테스트를 작성 |
@RepeatedTest | 반복되는 테스트를 작성 |
@TestFactory | @Test로 선언된 정적 테스트가 아닌 동적테스트를 사용 |
@TestInstance | 테스트 클래스의 생명주기를 설정 |
@TestTemplate | 공급자에 의해 여러 번 호출될 수 있도록 설계된 테스트 게이스 템플릿임을 나타냄 |
@TestMethodOrder | 테스트 메소드 실행순서를 구성에 사용 |
@DisplayName | 테스트 클래스 or 메소드의 사용자 정의 이름을 선언할 때 사용 |
@DisplayNameGeneration | 이름 생성기를 선언함. 예를들어 '_'를 공백으로 치환해주는 생성기가 있음 |
@BeforeEach | 모든 테스트 실행 전에 실행할 테스트에 사용 |
@AfterEach | 모든 테스트 실행 후에 실행할 테스트에 사용 |
@Nested | 클래스를 정적이 아닌 중첩 테스트 클래스임을 나타냄 |
@Tag | 클래스 또는 메소드 레벨에서 태그를 선언할 때 사용 |
@Diabled | 이 클래스나 테스트를 사용하지 않음 |
@Timeout | 테스트 실행 시간을 선언 후 초과하면 실패하도록 설정 |
@ExtendWith | 확장을 선언적으로 등록할 때 사용 |
@RegitserExtension | 필드를 통해 프로그래밍 방식으로 확장을 등록할 때 사용 |
@TempDir | 필드 주입 또는 매개변수 주입을 통해 임시 디렉토리를 제공하는데 사용 |
두 값을 비교하여 일치 여부 판단
assertEquals("불일치", expected, actual); 실패 시 반환할 메세지 설정 가능
@Test
public void test() {
String expected = "eunjy";
String actual = "eunjy";
assertEquals(expected, actual);
}
두 배열을 비교하여 일치 여부 판단
두 배열이 모두 null이어도 동일한 것으로 간주함
@Test
public void test() {
char[] expected = {'J','u','n','i','t'};
char[] actual = "Junit".toCharArray();
assertArrayEquals(expected, actual);
}
객체의 null 여부 확인
@Test
public void test() {
Object car = null;
assertNull("The car should be null", car);
}
두 변수가 동일한 객체를 참조하는지 확인
@Test
public void test() {
Object cat = new Object();
Object dog = new Object();
assertNotSame(cat, dog);
}
특정 조건이 true인지 false인지 판단
@Test
public void test() {
assertTrue("5 is greater then 4", 5 > 4);
assertFalse("5 is not greater then 6", 5 > 6);
}
AssertionFailedError를 발생시키는 테스트에 실패
실제 예외가 발생했는지 확인하거나, 개발 중에 테스트를 실패하게 만들고 싶을 때 사용
@Test
public void test() {
try {
methodThatShouldThrowException();
fail("Exception not thrown");
} catch (UnsupportedOperationException e) {
assertEquals("Operation Not Supported", e.getMessage());
}
}
모든 Assertion이 실행되고 실패가 함께 보고되는 그룹화된 Assertion
MultipleFailureError에 대한 메시지 문자열에 포함될 제목과 실행 가능한 스트림을 허용
실행 파일 중 하나에서 OutOfMemoryError가 발생한 경우에만 중단됨
메소드 내에서 인자로 람다식을 사용
여러 개의 람다식이 동시에 실행됨
@Test
public void test() {
assertAll(
"heading",
() -> assertEquals(4, 2 * 2, "4 is 2 times 2"),
() -> assertEquals("java", "JAVA".toLowerCase()),
() -> assertEquals(null, null, "null is equal to null")
);
}
예상 반복 가능 항목과 실제 반복 가능 항목이 동일한지 확인
두 Iterable은 동일한 순서로 동일한 요소를 반환해야 함
두 Iterable이 동일한 유형일 필요는 없음
아래에서 서로 다른 유형의 두 목록(LinkedList 및 ArrayList)이 동일한지 확인
@Test
public void test() {
Iterable<String> al = new ArrayList<>(asList("Java", "Junit", "Test"));
Iterable<String> ll = new LinkedList<>(asList("Java", "Junit", "Test"));
assertIterableEquals(al, ll);
}
예상 목록이 실제 목록과 일치하는지 확인
assertEquals, assertIterableEquals와 다름
예상 줄이 실제 줄과 같은지 확인
같으면 다음 쌍으로 이동
String.matches() 메서드로 검사
fast-forward marker 확인
아래에서 두 목록에 일치하는 행이 있는지 검사
@Test
public void test() {
List<String> expected = asList("Java", "\\d+", "JUnit");
List<String> actual = asList("Java", "11", "JUnit");
assertLinesMatch(expected, actual);
}
예상 값과 실제 값이 다름을 확인
@Test
public void test() {
Integer value = 5; // result of an algorithm
assertNotEquals(0, value, "The result cannot be 0");
}
특정 예외가 발생하였는지 확인
첫 번째 인자는 확인할 예외 클래스
두 번째 인자는 테스트하려는 코드
@Test
void test() {
Throwable exception = assertThrows(
IllegalArgumentException.class,
() -> {
throw new IllegalArgumentException("Exception message");
}
);
assertEquals("Exception message", exception.getMessage());
}
@Test
void test() {
Exception exception = assertThrows(ArithmeticException.class, () ->
calculator.divide(1, 0));
assertEquals("/ by zero", exception.getMessage());
}
특정 시간 안에 실행이 끝나는지 확인
시간 내 실행이 끝나는지 여부 확인 시 : assertTimeout
지정한 시간 내 끝나지 않으면 바로 종료 : assertTimeoutPreemptively
@Test
public void test() {
assertTimeout(
ofSeconds(2),
() -> {
// code that requires less then 2 minutes to execute
Thread.sleep(1000);
}
);
}