JVM/JUnit

[JUnit] 소개 - 3. Annotation (TestInstance, TestMethodOrder, Tag)

헹창 2023. 9. 21.
반응형

@TestInstance

  • 테스트 인스턴스의 라이프 사이클을 설정하는 어노테이션
  • 명시적으로 지정되지 않은 경우 기본 값 : PER_METHOD

라이프 사이클

  • PER_METHOD : 각 테스트 메소드마다 인스턴스가 생성
  • PER_CLASS : 테스트 클래스별로 테스트 인스턴스 생성

Example (PER_METHOD)

import org.junit.jupiter.api.Test
 
class Test {
    int number = 0;
 
    @Test
    fun add1() {
        number++
        System.out.println("[add1] number is " + number);
    }
 
    @Test
    fun add2() {
        number++
        System.out.println("[add1] number is " + number);
    }
}

쉽게 말해, 위와 같은 경우(Default = PER_METHOD)는

테스트 메소드 add1() 실행했을 때와 add2() 실행했을 때 Test 인스턴스를 각각 생성해 아래와 같이 출력된다.

[add1] number is 1
[add2] number is 1

Example (PER_CLASS)

import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
 
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class Test {
    int number = 0;
 
    @Test
    fun add1() {
        number++
        System.out.println("[add1] number is " + number);
    }
 
    @Test
    fun add2() {
        number++
        System.out.println("[add1] number is " + number);
    }
}

반면, PER_CLASS 로 설정한 경우 Test 인스턴스는 한 번 생성되어, 각 테스트 메소드 add1(), add2() 를 실행하므로

전역 변수 number를 공유하게 되어 다음과 같이 출력된다.

[add1] number is 1
[add1] number is 2

프로퍼티 설정

junit.jupiter.testinstance.lifecycle.default = per_class

PER_CLASS 언제 사용?

테스트 끼리는 상태를 공유하지 않고 격리되는 것이 좋지만, 순서대로 상태 값을 전달하는 등의 테스트가 필요한 경우에 유용하고, 테스트 인스턴스 생성하는데 비용이 많이 드는 경우에 유용하다.

 

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다"

추천인 코드 : AF8800551

 

@TestMethodOrder

테스트 순서를 정해주는 어노테이션

MethodName a - ㄱ 오름차순 (메소드명 동일한 경우 파라미터 타입명 오름차순)
DisplayName @DisplayName 오름차순
OrderAnnotation @Order(n) 오름차순
Radom 랜덤
Custom  

Example (Custom)

  • 메소드명 내림차순 커스텀 클래스 구현하여 사용
package com.effortguy.junit5.testMethodOrderAnnotation;
 
import org.junit.jupiter.api.MethodDescriptor;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.MethodOrdererContext;
import org.junit.platform.commons.util.ClassUtils;
 
import java.lang.reflect.Method;
import java.util.Comparator;
 
public class MethodNameReverse implements MethodOrderer {
 
    @Override
    public void orderMethods(MethodOrdererContext context) {
        context.getMethodDescriptors().sort(comparator);
    }
 
    private static final Comparator<MethodDescriptor> comparator = Comparator.<MethodDescriptor, String>
            comparing(descriptor -> descriptor.getMethod().getName())
            .thenComparing(descriptor -> parameterList(descriptor.getMethod())).reversed();
 
    private static String parameterList(Method method) {
        return ClassUtils.nullSafeToString(method.getParameterTypes());
    }
}
package com.effortguy.junit5.testMethodOrderAnnotation;
 
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
 
@TestMethodOrder(value = MethodNameReverse.class)
public class CustomTest {

	// ...
    
}

 

@Tag

  • 테스트 그룹을 만들어, 원하는 그룹만 테스트 실행할 때 사용
  • 하나의 테스트 메소드에 여러 태그 사용 가능

Example

  • 테스트 코드 사용 예제
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class Study {

    @Test
    @Tag("a")
    @Tag("b")
    @Tag("c")
    void test1() {
        // ...
    }

    @Test
    @Tag("a")
    void test2() {
        // ...
    }

    @Test
    @Tag("b")
    void test3() {
        // ...
    }

    @Test
    @Tag("c")
    void test4() {
        // ...
    }

    @Test
    @Tags({@Tag("a"), @Tag("b"), @Tag("c")})
    void test5() {
        // ...
    }

}
  • Edit Configurations → Build and Run → Tags 선택하여 설정 가능
    • a | b  : a 또는 b 태그를 가진 메소드 실행
    • a & b : a와 b 태그를 가진 메소드 실행
사용 가능한 연산자 설명
& AND
| OR
! NO

Example (CustomTag)

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Target(ElementType.METHOD)	// 이 애노테이션은 메소드에 사용 가능
@Retention(RetentionPolicy.RUNTIME)	// 이 애노테이션을 런타임시에까지 사용 가능
@Test   // jupiter annotation
@Tags({@Tag("a"), @Tag("b"), @Tag("c")})
public @interface AbcTest {
    ...
}
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class Study {

    @AbcTest
    void test1() {
        // ...
    }

    @Test
    @Tag("a")
    void test2() {
        // ...
    }

    @Test
    @Tag("b")
    void test3() {
        // ...
    }

    @Test
    @Tag("c")
    void test4() {
        // ...
    }

    @AbcTest
    void test5() {
        // ...
    }

}
728x90
반응형

댓글

추천 글