Junit(1)

이은재·2024년 2월 14일

section05부분의 Custom Annotation 부분은 미완성된 @LifeCycle이 존재하여 계속해서 수정할 예정

환경설정

  • 앞의 Java 버전 설명을 통해 나는 11 버전을 사용하고 싶었지만 여러 상황을 고려하여 17의 버전을 사용하였다.

  • Java 17버전을 사용하기위해 adoptium jdk17을 설치한다
    Mac OS를 사용하기 때문에 그에 맞는 설정을 진행한다
    [참고자료] https://wook-lab.tistory.com/21

JUnit이란?

  • Java Programing 언어용 유닛 테스트 프레임워크

  • 테스트의 결과는 test 클래스로 개발자에게 테스트의 방법과 클래스의 History를 공유 가능

  • 단정(assert) 메서드로 테스트 케이스의 수행 결과를 판별

  • 어노테이션으로 간결하게 지원(JUnit4부터)

section01.test

  • 목표 : JUnit5의 기본 어노테이션 사용

  • JUnit5는 세 개의 서브 프로젝트로 이루어져 있다.

    	1. Junit Platform
    		- JVM에서 테스트 프레임워크를 실행하기 위한 테스트 엔진을 제공한다.
    	2. Junit Jupiter
        	- Junit5에서 테스트를 작성하고 실행하기 위한 엔진을 제공한다.
        3. Junit Vintage
        	- Junit3, 4를 기반으로 돌아가는 테스트 엔진을 제공해준다 (하휘 호환용)
  • 테스트 클래스의 경우 한 개 이상의 @Test 어노테이션이 필요하며 한 개 이상의 생성자를 가지고있다.

  • 기본 어노테이션을 사용하기 위한 코드

    @Test
    @DisplayName("테스트 메서드 1")
    public void testMethod1() {

    }
    
    // @DisplayName어노테이션을 통해 설정한 이름 값으로 Test결과를 표기해준다.
  • 우선 순위 테스트
    @Test
    @DisplayName("displayName 우선순위 테스트")
    public void 테스트_메서드2() {

// @DisplayName과 중복 작성 시에는 @DisplayName에 부여한 테스트 이름이 우선권을 가진다.

    }

section02.test

  • 목표 : 테스트 메서드의 실행 전 후에 동작하는 어노테이션을 활용

  • 테스트가 실행되기 전 한 번만 실행되는 어노테이션

    @BeforeAll
    public static void beforeAll() {
        System.out.println("beforeAll")
        
        
    // 각각의 테스트 메서드가 실행되기 전 실행되나
    // @Test, @RepeatedTest, @ParameterizedTest, @TestFactory가 실행되기 전에 동작한다.
    // 주로 테스트 하기 전에 필요한 목업 데이터를 미리 세팅해줄 목적으로 사용된다.
  • 각각의 테스트 메서드가 동작한 직후 동작하는 어노테이션
    // 각각의 테스트 메서드가 동작한 직후 동작을 한다.
    // @Test, @RepeatedTest, @ParameterizedTest, @TestFactory가 실행된 이후 동작한다..
    // 주로 단위 테스트들이 수행된 이후 사용한 자원을 해제할 목적으로 사용한다.

    @AfterEach
    public void afterEach() {
        System.out.println("afterEach");
    }
  • 모든 단위 테스트 종료 후 한 번만 실행되는 어노테이션
    // 모든 단위테스트가 완전히 끝난 후 딱 한 번만 실행된다.

    @AfterAll
    public static void afterAll() {
        System.out.println("afterAll");
    }

section3.test

  • 목표 : JUnit에서 제공하는 테스트 관련 추가 어노테이션을 사용

  • 테스트를 무시하기 위한 어노테이션

    // 해당 테스트를 무시할 때 사용하는 어노테이션이다.
    // Junit4에서는 @Ignore와 동일한 기능으로 사용된다.

    @Disabled
    @Test
    public void testIgnore() {

    }
  • 설정한 시간 내에 테스트를 끝마치지 못하면 테스트 실패하는 어노테이션
    // 주어진 시간 안에 테스트가 끝나지 않으면 테스트가 실패한다.
    // value에는 시간을 정수형으로, unit 사용할 시간 단위를 기술한다.

    @Test
    @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS)
    public void testTimeout() throws InterruptedException{
        Thread.sleep(900);
    }
    
    // Thread.sleep(1000)을 초과하면 에러를 발생시킨다.
  • @Tag 어노테이션

    // @Tag 태그를 이용하여 테스트를 필터링 할 수 있다.
    // @Tag를 사용하기 위한 규칙
    // 1. 태그는 공백이나 null이 있으면 안된다.
    // 2. 다음 글자들은 포함하면 안된다 -> : . ( ) & ! |

    @Test
    @Tag("development")
    public void testTag1() {

    }

    @Test
    @Tag("production")
    public void testTag2() {

    }

    @Test
    @Tags(value = {@Tag("development"), @Tag("production")})
    public void testTag3() {

    }
    
    // 태그의 값에 따라 테스트 코드가 출력되거나 생략된다.
  • @Order 어노테이션
    // 테스트 메서드는 실행 순서가 보장되지 않지만 경우에 따라서는 (통합테스트 환경 등 ) 테스트의 순서가 중요한 경우도 있다.
    // 클래스 레벨에 @TestMethodOrder(MethodOrderer.OrderAnnotation.class) 어노테이션을 추가하고
    // 각 테스트 메서드에 @Order 어노테이션으로 순서를 지정하면 테스트 순서를 설정할 수 있다.
    // 클래스에 작성한 테스트 메서드의 순서는 MethodOrderer에 DisplayName, MethodName, OrderAnnotation, Random 등이 있다.

    @Test
    @Order(1)
    public void testFirst() {}

    @Test
    @Order(2)
    public void testSecond() {}

    @Test
    @Order(3)
    public void testThird() {}

section04.test

  • 수업목표 : 운영체제, JRE에 따라 테스트를 수행

  • 테스트 메서드는 특정 OS 환경에서만 테스트를 진행되게 할 수 있다.
    이 때, 특정 OS에서 무시되는 사유를 disabledReason에 기술하여
    테스트 코드가 무시되는 사유를 다른 사람도 함께 알 수 있게 한다.

  • @EnabledOnOs 어노테이션

    @Test
    @EnabledOnOs(value = OS.MAC, disabledReason = "맥에서만 테스트합니다.")
    public void testMAC() {}

    @Test
    @EnabledOnOs(value = {OS.WINDOWS, OS.LINUX},  disabledReason = "윈도우와 리눅스만 테스트합니다.")
    public void testWindowsAndLinux() {}

    @Test
    @DisabledOnOs(value = OS.WINDOWS, disabledReason = "윈도우 환경에서는 테스트를 무시합니다.")
    public void testDisabledOnWindows() {}
    
    // 각각의 환경에 맞게 Mac의 경우, Windows의 경우에 맞게 테스트 실행
  • @EnableOnJre 어노테이션
    // @EnableOnJre를 이용하여 특정 JRE 버전에서만 테스트 하는 것도 가능하다.
    // @DisabledOnJre를 이용하여 특정 JRE 버전에서만 테스트를 Disabled하는 것도 가능하다.
    // @EnableForJreRange를 이용하면 min과 max 속성 사이의 버전에서 테스트 하는 것도 가능하다.
    // (min만 작성시 min~최신버전까지, max만 작성 시 이전 버전부터 max까지만 테스트를 한다.)

    @Test
    @EnabledOnJre(value = JRE.JAVA_8, disabledReason = "JRE 1.8. 환경에서만 테스트합니다.")
    public void testJRE() {}

    @Test
    @EnabledOnJre(value = {JRE.JAVA_8, JRE.JAVA_17})
    public void testJRE8ANDJRE17() {}

    @Test
    @DisabledOnJre(value = JRE.JAVA_17)
    public void testDisabledJRE17() {}

    @Test
    @EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_17)
    public void testFromJRE8TOJRE17() {}

section05.test

  • 목표 : 원하는 어노테이션을 조합하여 커스텀 어노테이션을 생성 및 사용

  • @MacTest 어노테이션 생성

	// 생성된 어노테이션의 활용
    @MacTest
    public void testOnMacOS() {}

	//MacTest 어노테이션을 생성하기위한 어노테이션 인터페이스 파일
    
	@Retention(RetentionPolicy.RUNTIME)
	// Retention -> 어노테이션이 언제까지 유지될지 명시하는 것
	@Target(ElementType.METHOD)
	// Target -> 이 어노테이션에 적용될 수 있는 JAVA 요소의 종류를 지정
	@EnabledOnOs(value = OS.MAC, disabledReason = "맥 환경에서는 작동하지 않습니다.")
	@Test
	public @interface MacTest {
	
	}
  • @DevelopmentTest 어노테이션 생성
	// 생성된 어노테이션 활용
    @DevelopmentTest
    public void testDevelopmentCustomTag() {}
    
    //DevelopmentTest 어노테이션을 생성하기 위한 어노테이션 인터페이스 파일
    
    @Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.METHOD)
	@Tag("development")
	@Test
	public @interface DevelopmentTest {
	}
  • @TimeTest 어노테이션 생성
	// 생성된 어노테이션 활용
    @TimeTest
    public void testTime() throws InterruptedException{
        Thread.sleep(100);
    }
    
    //TimeTest 어노테이션을 생성하기 위한 어노테이션 인터페이스 파일
    
    @Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.METHOD)
	@Timeout(value = 1000, unit = TimeUnit.MILLISECONDS)
	@Test
	public @interface TimeTest {
	}
  • @LifeCycle 어노테이션 생성 (미완성)
    내가 원하는 결과는 @LifeCycle 커스텀 메서드를 생성 후 testLifeCycle()메서드 호출 시 @BeforeAll, @AfterEach, @AfterAll의 출력문을 선언해두고 모두 출력되도록 만들고 싶은데 여러 에러가 발생중에 있다.
	//생성된 어노테이션 활용
    
 	@LifeCycle
    	public void testLifeCycle() {
    	}
    
    // LifeCycle 어노테이션을 생성하기 위한 어노테이션 인터페이스 파일
    
    @Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.METHOD)
	@Test
	@BeforeAll
	@AfterEach
	@AfterAll
	public @interface LifeCycle {
	}
  • 가장 먼저 이런 식으로 작성 후 테스트를 실행했는데,
    org.junit.platform.commons.JUnitException: @BeforeAll method 'public void com.ohgiraffers.section05.custom.CustomAnnotationTests.testLifeCycle()' must be static unless the test class is annotated with @TestInstance(Lifecycle.PER_CLASS).
    이러한 경고 메세지가 발생하였다.

  • "@BeforeAll, @AfterAll의 경우 static으로 선언을 하여야한다"라는 에러가 출력되었다.

  • 이를 해결하기 위해 테스트 클래스 안에 각각 어노테이션을 선언하고 함수를 지정한 후 @LifeCycle어노테이션을 사용하는 메서드인 testLifeCycle() 내에 선언한 함수들을 실행시켜보았다.

    @LifeCycle
    public void testLifeCycle() {
        testbefore();
        test1();
        test2();
        afterEach();
        afterAll();
    }

    @BeforeAll
    public static void testbefore() {
        System.out.println("beforeAll");
    }

    public void test1() {
        System.out.println("test1");
    }

    public void test2() {
        System.out.println("test2");
    }

    @AfterEach
    public void afterEach() {
        System.out.println("afterEach");
    }

    @AfterAll
    public static void afterAll() {
        System.out.println("afterAll");
    }
  • Class Configuration라는 에러가 발생하였고, org.junit.platform.commons.JUnitException: @BeforeAll method 'public void com.ohgiraffers.section05.custom.CustomAnnotationTests.testLifeCycle()' must be static unless the test class is annotated with @TestInstance(Lifecycle.PER_CLASS)라고 출력되었다.

  • 수정하여도 같은 에러가 발생하였고, 또 다른 방법으로 수정해보기 위해 LifeCycle 어노테이션 인터페이스를 수정하였다.

	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.METHOD)
	@Test
	public @interface LifeCycle {
	}
  • LifeCycle 어노테이션 인터페이스를 수정 후 내가 원하는 방향으로 약간의 결과가 출력되었긴 했지만 LifeCycle 어노테이션을 통해서 출력된 것이 아니라고 생각되었다.

  • 완벽하게 수정하여 다시 이 곳에 작성할 예정이다.

0개의 댓글