자바의 Junit

포모·2020년 12월 16일
0

JAVA API

목록 보기
5/5

테스트 코드는 사실 공부할 생각이 없었습니다..
하지만 요번 3주차 미션을 진행하면서 기능이 변경될 때마다 모든 기능을 다시 테스트하는 일을 쉽지가 않았습니다.
그래서 테스트 코드에 도전해보기로 했습니다! 💪


Junit이란?

Java에서 독립된 단위 테스트(Unit Test)를 지원해주는 프레임워크입니다.


특징

  • 단위 테스트 Framework 중 하나
  • 단정문으로 테스트 케이스의 수행 결과를 판별
  • Annotation(@)으로 간결하게 사용 가능

단위 테스트(Unit Test)란?

소스 코드의 특정 모듈이 의도된 대로 작동하는 지 확인하는 검증 절차입니다.


Annotation

AnnotationDescription
@Test테스트 함수임을 보여줍니다.
@ParameterizedTest매개변수가 있는 함수의 경우 사용합니다.
@RepeatedTest반복 테스트를 위한 테스트 템플릿입니다.
@TestFactory동적 테스트를 위한 테스트 팩토리입니다.
@TestTemplate등록된 공급자가 반환한 호출 컨텍스트 수에 따라 여러번 호출되도록 설계된 테스트케이스 입니다.
@TestMethodOrder테스트 함수의 실행 순서를 정하는데 사용됩니다.
@DisplayName테스트 클래스 또는 함수에 대해 사용자가 지정한 이름을 표시해줍니다.
@DisplayNameGeneration테스트 클래스에 대해 사용자가 지정한 이름을 생성합니다.
@BeforeEach테스트 함수보다 먼저 실행됩니다.
@AfterEach테스트 함수가 끝난 후에 실행됩니다.
@BeforeAll클래스 내부의 모든 테스트 함수보다 먼저 실행되며 static이어야 합니다.
@AfterAll클래스 내부의 모든 테스트 함수 이후에 실행되며 static이어야합니다.
@Nested중첩된 구조로 테스트를 가능하게 합니다.
@Tag클래스 또는 함수에서 테스트를 필터링 하기위해 태그를 선언합니다.
@Disabled테스트 클래스 또는 테스트 메서드를 비활성화 하는데 사용됩니다.
@Timeout실행시간이 초과되는 경우 테스트 함수가 실패하는데 사용됩니다.
@ExtendWith선언적으로 단위 테스트간에 공통적으로 사용할 기능을 구현하여 확장합니다.
@RegisterExtension절차적 코드를 이용하여 공통 기능을 구현하고 확장합니다.
@TempDir라이프 사이클 방법 또는 테스트 방법에서 필드 주입 또는 매개 변수 주입을 통해 임시 디렉토리를 제공하는 데 사용됩니다.

@Tag 예제

@Tag("example")
public @interface MyInteface {
}

// tast 어노테이션 사용
@Example
@Test
void myInterfaceTest() {
    // ...
}

@BeforeAll 예제


@Test
void 맨_앞에_구분자_입력() {
    assertThrows(InvalidCarNameException.class ,
            () -> InputValidator.validNameInput(",이름1"));
}

@BeforeAll
static void 제일_먼저_실행() {
    System.out.print("하윙\n");
}


@Test 예제

  • 테스트가 수행되는 메소드를 의미

  • Junit은 각각의 테스트가 서로 영향을 주지 않고 독립적으로 실행됨을 원칙으로 @Test마다 객체를 생성합니다.

  • 테스트 클래스는 최소 하나 이상의 테스트 메서드를 포함하는 최상위 클래스여야 하며 abstractinterface이면 안되고 단일 생성자여야만 합니다.

class Test {
    @BeforeAll
    static void 초기_테스트_클래스_동작시_처음_수행() {

    }

    @BeforeEach
    void 테스트_함수_동작_이전에_수행() {

    }

    @Test
    void 테스트_함수() {

    }

    @Test
    void 실패용_테스트_함수() {
        fail("실패 테스트");
    }

    @Test
    @Disabled("비활성화 예제")
    void 활성화_되지_않은_테스트_함수() {
        // 테스트가 수행되지 않습니다.
    }

    @Test
    void 테스트_함수_2() {
        assumeTrue("가나다".equals("라마"));
        fail("테스트가 실패하였습니다.");
    }

    @AfterEach
    void 테스트_함수_끝난_후_동작() {
        System.out.print("테스트_함수_끝난_후_동작");
    }

    @AfterAll
    static void 테스트_클래스가_끝난_후_동작() {
        System.out.print("테스트_클래스가_끝난_후_동작");
    }
}
  • 테스트_함수_끝난_후_동작()은 총 3번 출력, 테스트_클래스가_끝난_후_동작()은 1번 출력됩니다.

  • 실패용_테스트_함수()


  • 테스트_함수_2()


@DisplayName 예제

테스트 함수 앞에 이 태그를 붙이고 이름을 설정해주면 다음과 같이 이름을 표시할 수 있습니다.


Assertions

AnnotationDescription
@assertAll(executeables ...)구문 오류시 예외를 발생시키지 않으면서 한번에 모든 구문을 확인할 수 있습니다.
@assertEquals(expected, actual)실제 값과 예상 값이 같은지 확인합니다. 이외 assertArrayEquals(), assertNotEquals()도 존재합니다.
@assertNotNull(actual)값이 NULL인지 확인합니다.
@assertTrue(Boolean)다음 조건이 참인지 확인합니다.
@assertThrows(expectedType, executable)예외를 발생 시키는 지 확인합니다.
@assertTimeout(timeout, executable)특정 시간 안에 실행하는 지 확인합니다.
@assertTimeoutPreemptively(timeout, executable)특정 시간 안에 실행하는 지 확인 후, 시간을 초과하면 실행이 중단되도록 설정합니다. 단, executable과 다른 스레드에서 실행하기 때문에 원치 않는 결과가 발생할 수 있습니다. (ex. 트랜잭션이 적용이 안되서 롤백이 안 되는 경우)

예제

class GameControllerTest {
    @DisplayName("AssertNotNull 함수")
    @Test
    public void 입력이_널인지_확인() {
        assertNotNull("하윙");
    }

    @DisplayName("AssertEquals 함수")
    @Test
    public void 값이_같은_지_확인() {
        String str = "입력";
        assertEquals("입력", str);
    }

    @DisplayName("AssertAll 함수")
    @Test
    public void 한번에_모든_구문을_확인() {
        List<String> list = Arrays.asList("일", "이", "삼", "사");
        for (String str : list) {
            assertAll("comment",
                    () -> assertNotNull(str),
                    () -> assertNotEquals("영", str));
        }
    }

    @DisplayName("AssertTrue")
    @Test
    public void 값이_참인지_확인() {
        assertTrue(5 > 4, () -> "5는 4보다 크다");
    }

    @DisplayName("AssertTimeOut")
    @Test
    void 작업_시간이_얼마나_초과했는지_체크() {
        assertTimeout(Duration.ofMillis(100), () -> {
            Thread.sleep(99);
        });
    }

    @DisplayName("AssertTimeoutPreemptively")
    @Test
    void 작업_시간_초과_시_에러_메세지() {
        assertTimeoutPreemptively(Duration.ofMillis(101), () -> {
            Thread.sleep(1);
        });
    }
}

🛴 마무리

테스트코드에서 그동안 정말 많이 찾아보고 봐왔었는데,
여태까지는 왜 이렇게 이해가 안 갔던 것인지..
이번에 차분하게 다시 정리해보았는데요, 이제 조금씩 이해가 가기 시작하네여

이어지는 글로 제가 직접 사용한 테스트 코드를 가져와보겠습니다.😊

0개의 댓글