본문 바로가기

Backend/JAVA

JUnit5의 기본적인 사용법들

🔐 JUnit5란?

세 가지 모듈(JUnit Platform + JUnit Jupiter + JUnit Vintage)로 구성된 테스트 라이브러리로, Java 8 이상부터 제공합니다.

  • JUit Platform
    • JVM에서 테스트를 하기 위한 기반 역할을 한다.
    • 테스트 프레임 워크를 개발하기위한 API를 정의한다.
    • JUnit4 기반 실행 환경을 제공한다.
  • JUnit Jupiter
    • JUnit5에서 새롭게 탄생한 프로그래밍 모델과 확장 모델의 조합이다.
    • Jupiter 기반 테스트를 실해앟기 위한 TestEngine을 제공한다.
  • JUnit Vintage
    • JUnit3, JUnit4 기반 테스트를 실행하기위한 TestEngine을 제공한다.

💛 사용해보기

모든 예제는 공식 문서에 있는 예제들을 기반으로 작성되었습니다.

1. @Test

@Test
void basic() {
  assertEquals(2, 1 + 1);
}

해당 메서드가 테스트 메서드임을 나타냅니다.

JUnit5 JUnit4

JUnit4의 @Test와는 달리 속성을 지원하지 않습니다.

 

2. @ParameterizedTest

@ParameterizedTest
@ValueSource(ints = { 1, 5 })
void isPositive(int number) {
  assertTrue(number > 0);
}

파라미터 테스트를 할 수 있게 도와주는 어노테이션으로, @ValueSource를 통해 매개변수를 지정할 수 있습니다.

 

개별로 테스트가 진행되며, 테스트에 실패할 시 실패한 부분에 대한 로그를 보여줍니다.

 

3. @RepeatedTest

@RepeatedTest(5)
void repeatedTest() {
  System.out.println("테스트 반복!");
}

반복된 테스트를 하기 위해 사용되는 어노테이션입니다.

 

4. @TestMethodOrder

@TestMethodOrder(OrderAnnotation.class)
class OrderedTestsDemo {
  @Test
  @Order(2)
  void secondTest() {
    System.out.println("2");
  }

  @Test
  @Order(1)
  void firstTest() {
    System.out.println("1");
  }

  @Test
  @Order(3)
  void thirdTest() {
    System.out.println("3");
  }
}

우선 순위에 따라 테스트를 실행할 수 있도록 도와주는 어노테이션입니다. @Order를 통해 우선순위를 지정할 수 있습니다.

 

5. @TestInstance

@TestInstance(Lifecycle.PER_CLASS)
class OrderedTestsDemo {
	// ...
}

라이프 사이클을 지정할 수 있는 어노테이션입니다.

 

6. @DisplayNameGeneration

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
public class DisplayNameGenerationTest {
  @Test
  void 기본_산수를_검증하는_테스트() {
    assertEquals(2, 1 + 1);
  }
}

테스트 이름 템플릿을 지정할 수 있는 어노테이션입니다. 해당 예제는 메소드 이름의 언더스코어(_)를 제거해주는 역할을 하는 클래스입니다.

👀 만약 intellJ를 사용하는데 테스트 이름이 바뀌지 않는다면, Setting-Build, Execution, Deployment-Gradle-Run tests usingIntelliJ IDEA로 바꿔주세요!

 

7. @DisplayName

@DisplayName("기본 산수를 검증하는 테스트")
@Test
void basic() {
  assertEquals(2, 1 + 1);
}

테스트 이름을 지정할 수 있는 어노테이션입니다. (위 방법 보다는 이 방법이 더 좋은 것 같네요!)

 

8. @BeforeEach, @AfterEach

@TestMethodOrder(OrderAnnotation.class)
class OrderedTestsDemo {
  @BeforeEach //JUnit4 @Before와 같음
  void beforeEachTest() {
    System.out.println("----start----");
  }

  @AfterEach //JUnit4 @After와 같음
  void afterEachTest() {
    System.out.println("----end----");
  }

  @Test
  @Order(2)
  void secondTest() {
    System.out.println("2");
  }

  @Test
  @Order(1)
  void firstTest() {
    System.out.println("1");
  }

  @Test
  @Order(3)
  void thirdTest() {
    System.out.println("3");
  }
}

테스트 메서드가 시작하기 전, 후에 각각 실행하는 어노테이션입니다. JUnit4에 존재했던 @Before, @After와 하는 일이 동일합니다.

 

8. @BeforeEach, @AfterEach

@TestInstance(Lifecycle.PER_CLASS)
@TestMethodOrder(OrderAnnotation.class)
class OrderedTestsDemo {
  @BeforeAll //JUnit4 @BeforeClass와 같음
  void beforeAllTest() { 
    System.out.println("*----all start----*");
  }

  @AfterAll //JUnit4 @AfterClass와 같음
  void afterAllTest() {
    System.out.println("*----all end----*");
  }

  @Test
  @Order(2)
  void secondTest() {
    System.out.println("2");
  }

  @Test
  @Order(1)
  void firstTest() {
    System.out.println("1");
  }

  @Test
  @Order(3)
  void thirdTest() {
    System.out.println("3");
  }
}

테스트 클래스 단위로 테스트 전, 후에 각각 실행하는 어노테이션입니다. JUnit4에 존재했던 @BeforeClass, @AfterClass와 하는 일이 동일합니다. 또한 정적(static) 메소드가 아니면 @TestInstance(Lifecycle.PER_CLASS)를 사용해야합니다.

 

9. @Nested

public class NestedTests {

  @TestInstance(Lifecycle.PER_CLASS)
  @Nested
  class Positive {

    @BeforeAll
    void startTest() {
      System.out.println("테스트 시작");
    }

    @Test
    void isPositive() {
      assertTrue(1 > 0);
    }
  }

  @Nested
  class Negative {
    @Test
    void isNegative() {
      assertTrue(-1 < 0);
    }
  }
}

중첩 클래스 테스트라는 것을 명시하는 어노테이션입니다. @BeforeAll 또는 @AfterAll를 사용하려면 수명 주기를 명시해야합니다.

 

10. @Tag

@Tag("number")
@Test
void basic() {
  assertEquals(2, 1 + 1);
}

태그를 선언하는 어노테이션입니다. 추후에 구성 설정 파일을 통해 테스트에 포함 시킬 태그를 선택하거나, 제외시킬 태그를 선택할 수 있습니다. JUnit4의 @Category가 이 어노테이션으로 대체되었습니다.

 

junitPlatform {
  filters {
      tags {
          include 'number', 'korean'
          exclude 'english'
      }
  }
}

 

11. @Disabled

@Disabled
@Test
void ignoredTest() {
  System.out.println("테스트 하지 않습니다!");
}

테스트에서 제외시키는 어노테이션입니다. JUnit4의 @Ingore과 하는 일이 동일합니다.

 

12. @Timeout

@Timeout(1)
@Test
void mustRunIn1SecondTest() throws InterruptedException {
	Thread.sleep(1500); // 실패
}

실행 시간 제한을 걸어두는 어노테이션입니다. 시간이 초과되면 TimeoutException이 발생하며 테스트가 실패합니다.

 

13. @ExtendWith

@ExtendWith(RandomParametersExtension.class)
@Test
void test(@Random int random) {
  System.out.println("랜덤 숫자 : " + random);
}

테스트 메소드에 특정 클래스를 확장하는 어노테이션입니다. (예제코드에 나온 RandomParametersExtension.class는 공식문서에 있는 코드를 참고했습니다.) JUnit4의 @RunWith@Rule이 해당 어노테이션으로 대체되었습니다.


💦 소개하지 않은 어노테이션

사용할 일이 있을까? 싶어 소개하지 않은 어노테이션들입니다. 만약 사용해야하는 일이 생기게 된다면 따로 예제코드를 만들어 업로드할 예정입니다!

1. @TestFactory

동적인 테스트를 만들 때 사용됩니다.

2. @TestTemplate

반환된 호출 컨텍스트 수에 따라 반복적으로 호출되어야할 때 사용됩니다.

3. @RegisterExtension

필드를 통해 확장을 하고 싶을 때 사용됩니다. (JUnit4의 @ClassRule이 이 어노테이션으로 대체되었습니다.)

4. @TempDir

테스트를 위한 임시 디렉토리를 사용해야할 때 사용됩니다.


✨ 정리

JUnit4를 언제까지고 쓸 수 없어서 JUnit5를 익혔는데 생각한 것 만큼 어렵지 않아서 쉽게 익힐 수 있었습니다! 혹시나 아직까지 JUnit4를 사용하시는 분이 계시다면 저처럼 JUnit5를 시도해보는 것도 좋은 선택인 것 같습니다 ㅎㅎ

혹시 글을 읽으면서 잘못된 내용이 있으면 댓글로 알려주시면 감사하겠습니다! 읽어주셔서 감사합니다! 😊


👏 참고