JUNIT 정리

seop93·2022년 10월 31일

JUnit이란

Unit(제이유닛)은 자바 프로그래밍 언어용 유닛 테스트 프레임워크이다. JUnit은 테스트 주도 개발 면에서 중요하며 SUnit과 함께 시작된 XUnit이라는 이름의 유닛 테스트 프레임워크 계열의 하나이다.
JUnit은 컴파일 타임에 JAR로서 링크된다. 프레임워크는 JUnit 3.8 이하의 경우 junit.framework 패키지 밑에 상주하며, JUnit 4 이상의 경우 org.junit 패키지 밑에 상주한다. -나무위키

JUnit5

이전 JUnit 버전과 다르게, JUnit5는 세개의 서브 프로젝트로 이루어져 있다.
JUnit5 은 JUnit Platform + JUnit Jupiter + JUnit Vintage 이 세개가 합친 것 이다.

  • JUnit platform은 JVM에서 테스트 프레임 워크를 실행하는데 기초를 제공한다. 또한 TestEngine API를 제공해 테스트 프레임워크를 개발할 수 있다.

  • JUnit Jupiter는 JUnit에서 테스트를 작성하고 확장을 하기 위한 새로운 프레그래밍 모델과 확장 모델의 조합이다.

  • JUnit Vintage는 하위호환성을 위해 JUnit3 와 JUnit4를 기반으로 돌아가는 플랫폼에 TestEngine을 제공해준다.

어노테이션

테스트를 구성하고, 프레임워크를 상속하기 위해서 다음과 같은 어노테이션을 지한다.
따로 명시하지 않으면 대부분 JUnit-Jupiter-api모듈 안으로 org.junit.jupiter.api 패키지안에 존재한다.

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class MyFirstJUnitJupiterTest {

    private final Calculator calculator= new Calculator();

    @Test
    void addition(){
        assertEquals(2,calculator.add(1,1));
    }

}
package org.example;

public class Calculator {
    public Calculator(){

    }

    public int add(int a, int b){
        return a + b;
    }
}

  • @DisplayName: 테스트 클래스나 테스트 메소드에 이름을 붙여줄 때 사용
@DisplayName("테스트 메소드의 이름 보통은 목적 작성")
  • @DisplayNameGeneration: 클래스에 해당 어노테이션을 붙이면 @Test 메소드에 이름에 언더바(_)로 표시한 모든 부분을 공백으로 처리

  • @BeforeEach: 각각의 테스트 메소드가 실행되기 전에 실행되어야 하는 메소드를 명시해준다. @Test,RepeatedTest,ParameterizedTest,TestFactory 가 붙음 테스트 메소드가 실행하기 전에 실행된다. JUnit4의 @Before와 같은 역할을 한다. 개인적으로 테스트하기 전에 필요한 목업 데이터를 미리 세팅해주기 위해 주로 사용한다.

  • @Test: 테스트 Method임을 선언(정적 테스트)

  • @AfterEach:@Test,@RepeatedTest,@ParameterizedTest,@TestFactory가 붙은 테스트 메소드가 실행되고 난 후 실행된다.

  • @BeforeAll:@BeforeEach각 테스트 메소드 마다 실행되지만, 이 어노테이션은 테스트가 시작하기 전 한 번만 실행 된다.

  • @AfterAll: 이것도 위와 같다. 테스트가 완전히 끝난 후 딱 한 번만 실행 된다.

  • @📌Nested: test클래스 안에 Nested테스트 클래스를 작성할 때 사용되며, static이 아닌 중첩클래스, 즉 Inner 클래스이여만 한다. 테스트 인스턴스 라이플 사이클이 per-class 로 설정되어 있지 않다면 @BeforeAll,@AfterAll가 동작안하니 주의하자. 테스트 인스턴스 라이플 사이클은 밑의 내용에서 한번 더 언급 된다.

  • @📌Tag:테스트를 필터링할 때 사용한다. 클래스 또는 메소드레벨에 사용한다.
    📌

  • @Disabled: 테스트 클래스나, 메소드의 테스트를 비활성화 한다. JUnit4의 @Ignore와 같다.

  • @📌Timeout: 주어진 시간안에 테스트가 끝나지 않으면 실패한다.

  • @📌ExtendWith:extension을 등록한다. 이 어노테이션은 상속이 된다. 확장팩이라고 생각하면 될 것 같다. 확장을 선언적으로 등록할 때

  • @RegisterExtension: 필드를 통해 extension을 등록한다. 이런 필드는 private이 아니라면 상속된다.

  • @TempDir: 필드 주입이나 파라미터 주입을 통해 임시적인 디렉토리를 제공할 때 사용한다.

  • @ParameterizedTest: 매개변수를 받는 테스트 작성

  • @RepeatedTest: 반복되는 테스트 작성

  • @TestFactory: 동적으로 테스트를 사용함

  • @TestInstance: 테스트 클래스의 생명주기 설정

  • @TestTemplate: 공급자에 의해 여러 번 호출될 수 있도록 설계된 테스트 케이스 템플릿임을 나타냄

  • @TestMethodOrder: 테스트 메소드 실행 순서 구성에 사용

  • @RegisterExtension: 필드를 통해 프로그래밍 방식으로 확장을 등록할 때 사용

JUnit4 Assertions

1.assertEquals

  • 두 값을 비교하여 일치 여부 판단
  • assertEquals(expected,actual); 실패시 반환할 메세지 설정 가능

2.asserArrayEquals

  • 예상 배열과 실제 배열이 동일한지 확인
  • 배열이 같지 않으면 마지막 인자로 들어간 메세지가 출력됨
    @Test
    public void test(){
        char[] expected = {'u','n','i','t'};
        char[] actual = "unit1".toCharArray();

        assertArrayEquals(expected, actual,"not equal");
    }

3.assertNotNull & assertNull

  • 객체의 null여부 확인

4.assertNotSame & assertSame

  • 예상되는 값과 실제 값이 동일한 객체를 참조하는지 확인

5.assertTrue & assertFalse

  • 특정 조건이 true 인지 false 인지 판단
    public void test2(){
        BooleanSupplier condition = () -> 5 <6;
        assertFalse(condition, " 5 is not greater then 6");
    }

6.fail

  • 제공된 실패 메시지와 기본 원인으로 테스트에 실패
  • 개발이 완료되지 않은 테스트를 표시하는데 유용
    @Test
    public void test(){
        //Test not completed
        fail("FAIL - test not completed");
    }

7.assertAll

  • 모든 Assertion이 실행되고 실패가 함께 보고되는 그룹화된 Assertion
  • MultipleFailureError 에 대한 메시지 문자열에 포함될 제목과 실행 가능한 스트림을 허용
  • 실행 파일 중 하나에서 OutOfMemoryError가 발생한 경우에만 중단됨
  • 메소드 내에서 인자로 람다식을 사용 여러개의 람다식 사용
    @Test
    public void test(){
        assertAll(
                "heading",
                ()->assertEquals(4,2*2,"true wow"),
                ()->assertEquals("java", "JAVA".toLowerCase())

        );
    }

8.📌assertIterableEquals

  • 예상 반복 가능 항목과 실제 반복 가능 항목이 동일한지 확인
  • 두 Iterable은 동일한 순서로 동일한 요소를 반환해야 함
  • 두 Iterable이 동일한 유형일 필요는 없음
  • 아래에서 서로 다른 유형의 두 목록(LinkedList 및 ArrayList)이 동일한지 확인

9.📌assertLinesMatch

  • 예상 목록이 실제 목록과 일치하는지 확인
  • assertEquals, assertIterablEquals와 다름
    1.예상 줄이 실제 줄과 같은지 확인
    2.같으면 다음 쌍으로 이동
    3.String.matches()메서드 검사
    4.fast-forward maker확인

-아래에서 두 록에 일치하는 행이 있는지 검사

10.assertNotEquals

  • 예상 값과 실제 값이 다름을 확인
    @Test
    public void test(){
        Integer value = 5;
        
        assertNotEquals(0,value,"The result cannot be 0");

    }

11.assertThrows

  • 특정 예외가 발생하였는지 확인
  • 첫 번째 인자는 확인할 예외 클래스
  • 두 번째 인자는 테스트하려는 코드
   @Test
    public void test(){
        Throwable exception = assertThrows(
                IllegalArgumentException.class,
                () -> {
                    throw new IllegalArgumentException("Exceotion message");
                }
        );
        assertEquals("Exception message",exception.getMessage());

    }

12.📌assertTimeout & assertTimeoutPreemptively

  • 특정 시간 안에 실행이 끝나는지 확인
  • 시간 내 실행이 끝나는지 여부 확인 시 :assertTimeout
  • 지정한 시간 내 끝나지 않으면 바로 종료:assertTimeoutPreemptively
    @Test
    public void test(){
    assertTimeout(
            Duration.ofSeconds(2),
            ()->{
                Thread.sleep(1000);
            }
    );
    }

메타 어노테이션과 컴포즈 어노테이션

JUnit Jupiter 어노테이션은 메타 어노테이션처럼 사용된다. 그 말은 즉슨 자동으로 메타 어노테이션을 상속하는 자기만의 컴포즈 어노테이션을 정의할 수 있다.

ex)Tag("fast")를 복사 붙여 넣기 하기보다 커스텀 컴포즈 어노테이션인 @Fast를 하나 만든 다음 Tag("fast")를 대체하여 사용하는 것이다.

package org.example;

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;


class MyFirstJUnitJupiterTest {

    private final Calculator calculator= new Calculator();

    @Tag("fast")
    public @interface Fast{}
    
    @Fast
    @Test
    void MyFastTest(){}
}    

더 나아가서 Tag("fast")@Test 를 합쳐 @FastTest로 만들어도 좋다. 이렇게 자신만의 컴포즈 어노테이션을 만들면, 간편하게 사용할 수 있다.

테스트 클래스와 메소드

테스트 클래스란 최상위 클래스, 스태틱 멤버 클래스,@Nested클래스에 적어도 한개의 @Test어노테이션이 달린 테스트 메소드가 포함되있는 걸 말한다. 테스트 클래스는 abstract이면 안되고, 하나의 생성자가 있어야 한다.

생성자가 없으면, 컴파일러가 자동으로 빈 생성자를 만들어준다.

테스트 메소드란 @Test,@RepeatedTest,@ParameterizedTest,@TestFactory,@TestTemplate 같은 어노테이션이 메소드에 붙여진 메소드를 말한다.

라이플사이클 메소드란
@BeforeAll,AfterAll,@BeforeEach,@AfterEach 같은 어노테이션이 메소드에 붙여진 메소드를 말한다.

테스트 메소드와 라이플 사이클 메소드는 테스트 할 클래스, 상속한 부모클래스 또는 인터페이스에 선언된다. 추가로 테스트와 라이플 사이클 메소드는 abstract선언하면 안되고, 어떠한 값도 리턴되선 안된다.

profile
팀에 도움이 되고 싶은 개발자

0개의 댓글