
Unit(제이유닛)은 자바 프로그래밍 언어용 유닛 테스트 프레임워크이다. JUnit은 테스트 주도 개발 면에서 중요하며 SUnit과 함께 시작된 XUnit이라는 이름의 유닛 테스트 프레임워크 계열의 하나이다.
JUnit은 컴파일 타임에 JAR로서 링크된다. 프레임워크는 JUnit 3.8 이하의 경우 junit.framework 패키지 밑에 상주하며, JUnit 4 이상의 경우 org.junit 패키지 밑에 상주한다. -나무위키
이전 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("테스트 메소드의 이름 보통은 목적 작성")
@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: 필드를 통해 프로그래밍 방식으로 확장을 등록할 때 사용
assertEquals(expected,actual); 실패시 반환할 메세지 설정 가능 @Test
public void test(){
char[] expected = {'u','n','i','t'};
char[] actual = "unit1".toCharArray();
assertArrayEquals(expected, actual,"not equal");
}
public void test2(){
BooleanSupplier condition = () -> 5 <6;
assertFalse(condition, " 5 is not greater then 6");
}
@Test
public void test(){
//Test not completed
fail("FAIL - test not completed");
}
@Test
public void test(){
assertAll(
"heading",
()->assertEquals(4,2*2,"true wow"),
()->assertEquals("java", "JAVA".toLowerCase())
);
}
-아래에서 두 록에 일치하는 행이 있는지 검사
@Test
public void test(){
Integer value = 5;
assertNotEquals(0,value,"The result cannot be 0");
}
@Test
public void test(){
Throwable exception = assertThrows(
IllegalArgumentException.class,
() -> {
throw new IllegalArgumentException("Exceotion message");
}
);
assertEquals("Exception message",exception.getMessage());
}
@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선언하면 안되고, 어떠한 값도 리턴되선 안된다.