자바 단위 테스트에 대해 알아보자

Jii·2023년 11월 2일
0

우테코

목록 보기
4/5
post-thumbnail

테스트 종류

테스트에는 단위 테스트(Unit Test)와 통합 테스트(Integration Test)가 존재합니다.

단위 테스트

하나의 함수(메서드)의 기능이 올바르게 작동하는지 테스트하는 것으로, '이 기능을 실행하면 이러한 결과가 나온다'를 테스트 하는 것입니다.

이 때 메서드는 public 메서드를 의미합니다.
private 메서드들은 대부분 public 메서드 안에서 활용되기 때문에, 따로 단독으로 테스트 할 필요가 없으며, public 메서드 테스트 시 함께 테스트가 실행될 것입니다.
(만약 private 메서드가 중요한 로직이라 꼭 테스트해야한다면, 그 메서드는 다른 클래스로 분리해야된다는 신호라고 생각합니다.)

통합 테스트

애플리케이션이 잘 작동하는지 테스트하는 것으로, 애플리케이션을 구성하고 있는 여러 메서드들이 서로를 호출하면서 프로그램이 올바르게 동작하는 지 확인합니다.
예를 들어 웹페이지라면 테스트 시 API까지 호출하여 프로그램이 잘 돌아가는 지 확인하는 것이며,
2주차 과제였던 자동차 경주게임에 비유하자면 시작 시 차 이름을 받는 거부터 시작해서 전진, 우승자 출력까지의 흐름이 올바르게 동작하는지 확인하는 것입니다.

이번 포스팅은 단위 테스트에 대해 집중적으로 다루겠습니다!

단위 테스트 장점

이번 단위 테스트를 작성하면서 느낀 장점은 다음과 같습니다.

  1. 리팩토링 혹은 새로운 기능 구현 시 기존에 구현해두었던 기능들이 올바르게 동작하는 지 빠르게 검증이 가능하여 시간 절약 및 안정성을 확보할 수 있습니다.
  2. 함수 하나 하나 테스트를 하기 때문에, 에러 발생 시 어느부분에서 발생하는 것인지 빠르게 파악이 가능합니다.
  3. 함수가 어떤 기능을 하며, 어떠한 결과를 반환하는 지를 나타내므로 코드에 대한 문서가 될 수 있습니다.

주로 이용하는 테스트 조합

  • Junit5: 단위 테스트를 돕는 테스팅 프레임워크 (자바 8부터 지원)
  • AssertJ: 테스트 작성 시 다양한 문법을 지원하는 라이브러리
    (Junit5에도 다양한 문법들이 존재하지만, AssertJ에 비해 가독성이 떨어져, 많은 분들이 저 둘의 조합을 애용하고 있습니다)

JUnit5의 주요 Annotations

  • @BeforeAll: 어노테이션이 사용된 클래스의 모든 테스트 실행 전 한번만 실행됨
  • @BeforeEach: 각 테스트 메서드가 실행되기 전에 매번 실행됨
  • @AfterAll: 클래스 내의 모든 테스트 메서드 실행 종료 후에 한번만 실행됨
  • @AfterEach: 각 테스트 메서드 실행 종료 시마다 실행됨
  • @Timeout : 주어진 시간안에 테스트가 끝나지 않으면 실패
  • @DisplayName: 테스트 메서드를 사용자가 지정한 이름으로 나타냄(공백, 특수문자, 이모지 등 입력 가능)
  • Disabled: 테스트를 비활성화시켜 skip할 수 있게함 (만약 고쳐야 하는 에러 발생 시 이 테스트만 skip하고 나머지가 잘 돌아가는 지 확인할 수 있겠다)

🔔 주의 - @BeforeAll, @AfterAll 은 한 번만 동작해야 하므로 static으로 선언되어야 한다.

Parameter를 사용하여 반복되는 코드 줄이기

  1. @Test가 아닌 @ParameterizedTest 어노테이션 지정
  2. @ValueSource와 같은 인자 선언
  3. 테스트 메서드에 매개변수로 인자 타입 및 이름 넣어주기
  4. 코드 내에서 인자가 사용될 부분 매개변수로 지정해준 이름 넣어주기

주로 사용하는 인자들

  • @ValueSource: 하나의 배열로 값을 정의하며, 하나의 인자에 대해서만 적용할 수 있습니다.
    타입: String, int, byte, short, long, float, double, char, boolean

    위와 같이 파라미터를 이용하면 아래와 같은 반복을 줄일 수 있게됩니다👍🏻
  • @NullSource: 파라미터 값으로 null을 넣어줌
  • @EmptySource: 파라미터 값으로 empty을 넣어줌
  • @NullAndEmptySource: 위의 두 개를 사용한 것과 같은 결과로 null과 empty를 함께 제공해주며, @ValueSource와 함께 사용 가능합니다.
@ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = { " ", "   ", "\t", "\n" })
void nullEmptyAndBlankStrings(String text) {
   assertTrue(text == null || text.trim().isEmpty());
}
  • @MethodSource: 하나 이상의 테스트 클래스 또는 외부 클래스 팩토리 메서드를 참조시 사용하며 factory메서드가 리턴해주는 데이터를 받아와 테스트 시 인자로 사용합니다.
    즉 동적 데이터 생성이 필요한 경우에 사용됩니다.
    이때 factory 메서드는 반드시 static이어야 하며, 인자 없이 stream 타입으로 리턴하여야 합니다.
@ParameterizedTest
@MethodSource("dataProviderMethod")
void testWithMethodSource(int value) {
    // 테스트 코드
}

static Stream<Arguments> dataProviderMethod() {
    // 데이터를 생성하고 Arguments로 래핑하여 반환 (테스트 메서드 인자 2개 이상일 시)
}
  • @CsvSource : 이름에서 알 수 있듯이, 리스트를 콤마를 기준으로 구분해 읽습니다.
@ParameterizedTest
@CsvSource({
    "John, 25",
    "Alice, 30",
    "Bob, 22"
})
void testWithCsvSource(String name, int age) {
    // 테스트 코드
}

""안에 매개변수로 넣어준 인자들의 데이터 값을 순서데로 넣어주면 되며, 여러 값을 테스트 해보고 싶을 시에는 ,를 이용하여 구분해주면 됩니다.
@CsvSource@MethodSource와 다르게 데이터를 직접 명시해줘야 한다는 차이점이 존재합니다.

참고 문헌

profile
Empower Yourself

0개의 댓글