Test

JUnit5

goodbye 2022. 12. 11. 14:01

Junit 5


 

  • 자바 개발자가 가장 많이 사용하는 테스팅 프레임워크
  • 단위 테스트 작성하는 자바 개발자 93% Junit 사용
  • 자바 8 이상 필요
  • 대체 : TestNG, Spock…

 

Junit5 Start


  • 2.2 + 이상의 버전의 스프링 부트 프로젝트부터 기본으로 JUnit 5 의존성이 추가

 

  • 스프링 부트 프로젝트 사용하지 않는다면
<dependency>     <groupId>org.junit.jupiter</groupId>     <artifactId>junit-jupiter-engine</artifactId>     <version>5.5.2</version>     <scope>test</scope> </dependency>

 

  • 기본 어노테이션
    • @Test
    • @BeforeAll
      • 테스트 클래스안에 있는 메서드가 실행되기전에 한번 호출
      • static void 로 사용, public 사용불가능
    • @AfterAll
      • 테스트 클래스안에 있는 메서드가 실행 후 한번 호출
      • static void 로 사용, public 사용불가능
    • @BeforeEach
      • 테스트 클래스안이 있는 각 메서드가 실행하기전에 한번씩 호출
    • @AfterEach
      • 테스트 클래스안이 있는 각 메서드가 실행하고나서 한번씩 호출
    • @Disabled
      • 해당 메서드의 테스트를 실행하지 않으려고 할때

 

  • 기본 어노테이션 실행 순서 확인

 

위와 같이 테스트 코드를 작성해보면 다음와 같이 순서대로 실행되는것을 확인할수 있다

 

  • 테스트를 생략하고 싶은 경우
    • @Disabled 어노테이션을 붙이면 아래와 같이 테스트가 생략된다

 

  • 테스트에 이름을 표시
    • @DisplayName
      • 어떤 테스트인지 테스트 이름을 보다 쉽게 표현할수 있는 방법을 제공하는 어노테이션
      • @DisplayNameGeneration 보다 우선 순위가 높다

    • @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
      • method와 class 래퍼런스를 사용해서 테스트 이름을 표기하는 방법 설정
      • 기본 구현체로 ReplaceUnderscores 제공
  • Run Test
    • 단축키 : Ctrl + Shift + R
    • 해당 메서드안에서 단축키 입력할경우 : 해당 테스트만 실행
    • 중립 영역에서 단축키 입력할 경우 : 해당 클래스 테스트 전체 실행

Juni5 : Assertion


  • 실제 값이 기대한 값과 같은지 확인 : assertEqulas(expected, actual)
    • assertEquals(기대값, 실제값, 실패메세지)
      • 실패메세지에 문자열 연산이 들어갈경우 테스트 성공, 실패와 관계없이 항상 문자열 연산 실행
    • assertEqyals(기대값, 실제값, () → 실패메세지)
      • 람다식으로 문자열을 생성하면 테스트가 실패했을때만 문자 연산을 실행한다
      • 성능에 유리함
  • 값이 null 이 아닌지 확인 : assertNotNull(actual)
  • 다음 조건이 참(true) 인지 확인 : assertTrue(boolean)
  • 모든 확인 구문 확인 : assertAll(executables…)
    • 람다표현식을 이용해서 Excutable Type 으로 묶어서 파라미터로 전달해서 전체 실행
    • 중간에 테스트가 실패와 상관없이 모든 테스트 실행 가능

 

  • Unchecked Exception 예와 발생 확인 : assertThrows(expctedType, executable)
    • assertThrows(unChecked Exception Class, () → 예외발생상황 )
    • when().thenThrow(Checked Exception.class)
      • void 특정_서비스 throws SqlException
  • 특정시간안에 실행이 완료되는지 확인 : assertTImeout(duration, executable)
  • AssertThat import

 

 

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


  • /Library/Java/JavaVirtualMachines/jdk-17.0.3.1.jdk/Contents/Home
  • 환경변수 등록
    • vi ~/.bash_profile
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-17.0.3.1.jdk/Contents/Home export PATH=${PATH}:$JAVA_HOME/bin
  • source ~/.bash_profile -echo $PATH

 

  • assumeTrue(조건)
  • assumingThat( 조건 , 테스트 )
    • 사용예시
    InteliJ 환경변수 등록
    assumeTrue, assumingThat 사용 예

 

  • @Enabled_ @Disabled_
    • EnabledOnOs, DisabledOnOs : OS 환경에 따라 실행여부 결정
      •  
    • EnabledOnJre, DisabledOnJre
    • EnabledIfEnvironmentVariable(named =”환경변수명”, matches=”환경변수값”)

 

  • 특정 테스트만 실행하고 싶은 경우
    • @Tag : 특정 테스트만 실행할 수 있도록 어노테이션 입력

Junit5 : Custom Tag


  • Junit5 애노테이션을 조합해서 커스텀 태그를 만들 수 있다
  • 오타를 줄일수 있고, Type Safe 하다는 장점이 있다

 

Junit5 : Test 반복하기


  • @RepeatedTest
    • 반복 횟수와 반복 테스트 이름을 설정 할 수 있다
      • {displayName}
      • {currentRepetition}
      • {totalRepetitions}
    • RepetitionInfo 타입의 인자를 받을 수 있다

    • 아래와 같이 코드를 작성하면 반복하면서 현재 반복횟수와 총 반복횟수를 기록 할 수 있다

    • @RepeatedTest( ) 안에 인자를 추가하여 다음과 같이 실행횟수와 총 실행횟수를 기록할수있다

 

  • @ParameterizedTest
    • 테스트에 여러 다른 매개변수를 대입하여 반복 실행 할수 있다
      • {displayName}
      • {index}
      • {arguments}
      • {0}, {1}, ….

 

 

Junit5 : Test Instance


  • Juit은 테스트 메서드 마다 테스트 인스턴스를 새로 만든다
    • 기본전략
    • 테스트 메서드를 독립적으로 실행하여 예상치 못한 부작용을 방지하기 위함
    • 이 전략을 JUnit5 에서 변경 할 수 잇다

 

  • @TestInstance(Lifecycle.PER_CLASS)
    • 테스트 클래스당 인스턴스를 하나만 만들어 사용
    • 경우에 따라 테스트 간에 공유하는 모든 상태를 @BeforeEach 또는 @AfterEach 에서 초기화 할 필요
    • @BeforeAll 과 @AfterAll
      • 인스턴스 메서드 또는 인터페이스에 정의한 default 메서드로 정의 가능
      • static keyword 생략 가능해진다
  • @TestMethodOrder
    • 테스트 메서드들의 순서를 정할수 있다
    • MethodOrderer 구현체를 설정
    • 기본 구현체
      • Alphanumeric
      • OrderAnnoation
      • Random
    • @Order(순서) 지정을 통해 테스트 순서가 보장된다
    •  

JUnit5 : junit-platform.properties


 

  • Junit 설정파일
  • src/test/rosources 경로에 넣어두면 적용
  • 테스트 인스턴스 라이프 사이클 설정
    • junit.jupiter.testinstance.lifecycle.default = per_class
  • 확장팩 자동 감지 기능
    • junit.jupiter.extensions.autodetection.enabled = true
  • @Disabled 무시하고 실행하기
    • junit.jupiter.conditions.deactivate = org.junit.*DisabledCondition
  • 테스트 이름 표기 전략 설정
    • junit.jupiter.displayname.generator.default = \org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores
    •  

JUnit5 : 확장모델


  • JUnit4 확장모델
    • @RunWith(Runner)
    • TestRule
    • MethodRule
  • JUnit5 확장모델
    • Extension
  • Extenstion 등록 방법
    • 선언적인 등록 @ExtendWith
    • 프로그래밍 등록 @RegisterExtension

 

  1. 선언적인 등록 @ExtendWith
    • 아래와 같이 CustomExtension Class 를 만들고

 

  • 테스트 클래스에 @ExtendWith 어노테이션에 CustomExtension 을 등록하고

 

  • 테스트 실행시간이 1초이상 걸리는 테스트를 실행하면

 

  • 다음과 같이 메세지가 출력된다

 

  1. 프로그래밍 등록 @RegisterExtension
    • CustomExtension 에서 필드의 값을 유동적으로 변경해서 사용하고 싶은 경우
    • CustomExtension 에 필드의 값을 주입하는 생성자를 만들고
    • Test Class 에 @RegisterExtension 어노테이션을 이용해서 생성자 값 주입
      • @ExtendWith 어노테이션에는 생성자를 사용할수없기때문

 

  1. 자동 등록 자바 ServiceLoader 이용 방법
     
    https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ServiceLoader.htm

 

  • 확장팩 만드는 방법
    • 테스트 실행 조건
    • 테스트 인스턴스 팩토리
    • 테스트 인스턴스 후-처리기
    • 테스트 매개변수 리졸버
    • 테스트 라이프사이클 콜백
    • 예외 처리
    • ...
JUnit 5 User Guide
All Events: Event [type = STARTED, testDescriptor = JupiterEngineDescriptor: [engine:junit-jupiter], timestamp = 2018-12-14T12:45:14.082280Z, payload = null] Event [type = STARTED, testDescriptor = ClassTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase], timestamp = 2018-12-14T12:45:14.089339Z, payload = null] Event [type = SKIPPED, testDescriptor = TestMethodTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase]/[method:skippedTest()], timestamp = 2018-12-14T12:45:14.094314Z, payload = 'for demonstration purposes'] Event [type = STARTED,
https://junit.org/junit5/docs/current/user-guide/#extensions

 

JUnit5 : JUnit4 마이그레이션


  • junit-vintage-engine을 의존성으로 추가하면, JUnit 5의 junit-platform으로 JUnit 3과 4로 작성된 테스트를 실행할 수 있다.
  • @Rule은 기본적으로 지원하지 않지만, junit-jupiter-migrationsupport 모듈이 제공하는 @EnableRuleMigrationSupport를 사용하면 다음 타입의 Rule을 지원한다.
    • ExternalResource
    • Verifier
    • ExpectedException