모르지 않다는 것은 아는것과 다르다.

Junit

Assertion

채마스 2022. 2. 27. 01:37

개요

  • Assertion 의 여러 기능들을 공부해 보려한다.



Assertion 의 여러 기능

  • import static org.junit.jupiter.api.Assertions.*
@Test
@DisplayName("스터디 만들기")
void create_new_syudy() {
  Study study = new Study();
  assertNotNull(study);
  assertEquals(StudyStatus.DRAFT, study.getStatus(), () -> "스터디를 처음 만들면 상태값이 DRAFT여야 한다.");
}
  • assertEqulas(expected, actual) : 실제 값이 기대한 값과 같은지 확인
  • assertNotNull(actual) : 값이 null이 아닌지 확인
  • assertTrue(boolean) : 다음 조건이 참(true)인지 확인



    @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
    public class StudyTest {
        @Test
        @DisplayName("스터디 만들기")
        void create_new_syudy() {
            Study study = new Study(-30);
            assertAll(
                    () -> assertNotNull(study),
                    () -> assertEquals(StudyStatus.DRAFT, study.getStatus(), 
                    () -> "스터디를 처음 만들면 상태값이 DRAFT여야 한다."),
                    () -> assertTrue(study.getLimit() > 0, 
                    () -> "스터디를 최대 참석 가능인원은 0보다 커야 한다."));
        }
    }
  • assertAll(executables...) : 모든 확인 구문 확인



    @Test
    @DisplayName("스터디 만들기")
    void create_new_syudy() {
      IllegalArgumentException exception =  
          assertThrows(IllegalArgumentException.class, () -> new Study(-10));
      String message = exception.getMessage();
      assertEquals("limit는 0보다 커야 한다.", message);
    }
  • assertThrows(expectedType, executable) : 예외 발생 확인



    @Test
    @DisplayName("스터디 만들기")
    void create_new_syudy() {
      //성공 예시
      //assertTimeout(Duration.ofSeconds(10), () -> new Study(10));
      //실패 예시
      assertTimeout(Duration.ofMillis(100), () -> {
        new Study(10);
        Thread.sleep(300);
      });
      }
  • assertTimeout(duration, executable) : 특정 시간 안에 실행이 완료되는지 확인
  • 마지막 매개변수로 Supplier 타입의 인스턴스를 람다 형태로 제공할 수 있다.
    • 복잡한 메시지 생성해야 하는 경우 사용하면 실패한 경우에만 해당 메시지를 만들게 할 수 있다.




조건에 따라 테스트 실행하기

  • 특정한 조건을 만족하는 경우에 테스트를 실행하는 방법
  • org.junit.jupiter.api.Assumptions.*
    @Test
    @DisplayName("스터디 만들기")
    void create_new_syudy() {
      String test_env = System.getenv("TEST_ENV");
      System.out.println(test_env);

      assumeTrue("LOCAL".equalsIgnoreCase(test_env));

      Study actual = new Study(10);
      assertThat(actual.getLimit()).isGreaterThan(0);
    }
  • 환경 변수가 Local이 아니면 그 아래 문장이 실행 안되고 끝남.



    @Test
    @DisplayName("스터디 만들기 ")
    void create_new_syudy() {
      String name = "hyunwook";

      assumingThat("hyunwook".equalsIgnoreCase(name), () -> {
        System.out.println("이름이 맞습니다.");
        Study actual = new Study(10);
        assertThat(actual.getLimit()).isGreaterThan(0);
      });

      assumingThat("test".equalsIgnoreCase(name), () -> {
        System.out.println("test 이름이 맞습니다.");
        Study actual = new Study(10);
        assertThat(actual.getLimit()).isGreaterThan(0);
      });
    }
  • assumeTrue(조건)
  • assumingThat(조건, 테스트)
    • @Enabled___ 와 @Disabled___
  • OnOS : ex> @EnabledOnOs({OS.WINDOWS, OS.LINUX})
  • OnJre : ex> @EnabledOnJre({JRE.JAVA_8, JRE.JAVA_9, JRE.JAVA_11})
  • IfSystemProperty
  • IfEnvironmentVariable : ex> IfEnvironmentVariable(name = "TEST_ENV", matches = "LOCAL")



태깅과 필터링

  • 테스트 그룹을 만들고 원하는 테스트 그룹만 테스트를 실행할 수 있는 기능
  • @Tag
    • 테스트 메소드에 태그를 추가할 수 있다.
    • 하나의 테스트 메소드에 여러 태그를 사용할 수 있다.
  • 인텔리J에서 특정 태그로 테스트 필터링 하는 방법이다.



커스텀 태그

  @Target(ElementType.METHOD)
  @Retention(RetentionPolicy.RUNTIME)
  @Tag("fast")
  @Test
  public @interface FastTest {
  }
  • @Retention(RetentionPolicy.RUNTIME) : 해당 애노테이션은 런타임까지 유지된다.
  • @Target(ElementType.METHOD) : 이 애노테이션은 어디에 쓸쑤있나 -> 메소드에 쓰겠다.



    @FastTest
    @DisplayName("스터디 만들기 fast")
    void create_new_study() {
    }
  • 커스텀한 @FastTest 를 쓰면 @Test, @Tag("faset")를 생략할 수 있다.



테스트 반복하기

  @DisplayName("반목문 테스트1")
  @RepeatedTest(value = 10, name = "{displayName}, {currentRepetition}/{totalRepetitions}") 
  void repeatedTest(RepetitionInfo repetitionInfo) {

      System.out.println("test" + repetitionInfo.getCurrentRepetition() + "/" + 
      repetitionInfo.getTotalRepetitions());
  }
  • @RepeatedTest
    • 반복 횟수와 반복 테스트 이름을 설정할 수 있다. -> value=반복횟수, name=테스트명
      • {displayName}
      • {currentRepetition}
      • {totalRepetitions}
    • RepetitionInfo 타입의 인자를 받을 수 있다.



테스트 인스턴스

  • JUnit은 테스트 메소드 마다 테스트 인스턴스를 새로 만든다.
    • 이것이 기본 전략.
    • 테스트 메소드를 독립적으로 실행하여 예상치 못한 부작용을 방지하기 위함이다.
    • 이 전략을 JUnit 5에서 변경할 수 있다.
  • @TestInstance(Lifecycle.PER_CLASS)
    • 테스트 클래스당 인스턴스를 하나만 만들어 사용한다.
    • 경우에 따라, 테스트 간에 공유하는 모든 상태를 @BeforeEach 또는 @AfterEach에서 초기화 할 필요가 있다.
    • @BeforeAll과 @AfterAll을 인스턴스 메소드 또는 인터페이스에 정의한 default 메소드로 정의할 수도 있다.



테스트 순서

  • 실행할 테스트 메소드 특정한 순서에 의해 실행되지만 어떻게 그 순서를 정하는지는 의도적으로 분명히 하지 않는다.
  • 경우에 따라, 특정 순서대로 테스트를 실행하고 싶을 때도 있다.
  • @TestInstance(Lifecycle.PER_CLASS)와 함께 @TestMethodOrder를 사용할 수 있다.
  @TestInstance(Lifecycle.PER_CLASS)
  @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
  • 위와 같이 class 위에 붙여주고
  • 각 테스트마다 @Order(1) 이런식으로 순서를 부여해 줄 수 있다.
    • 숫자는 낮을수록 높은 우선순위를 갖는다.




REFERENCES

'Junit' 카테고리의 다른 글

Mockito  (0) 2022.02.27
Junit5 애노테이션 비교  (0) 2022.02.27
# Junit 5 기본 애노테이션  (0) 2022.02.27
Controller 단위테스트  (0) 2022.02.27
Bad Request 처리하기  (0) 2022.02.27