기본 annotation 테스트
package hello.test;
import org.junit.jupiter.api.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
class StudyTest {
@Test
@DisplayName("학생 생성 테스트") //테스트 이름 정의
void create() {
Study study = new Study();
assertNotNull(study);
System.out.println("create1");
assertEquals(StudyStatus.NOTHING, study.getStatus(),"초기상태 WATING");
//기대값 //현재 상태
assertEquals(StudyStatus.NOTHING, study.getStatus(), () -> "초기값은 NOTHING 이어야 합니다.");
//lambda 식으로 변경(lambda로 변경하는 경우 해당 수행이 실패하는 경우에만 message연산을 수행
assertAll(
() -> assertNotNull(study),
() -> assertEquals(StudyStatus.NOTHING, study.getStatus(), () -> "초기값은 NOTHING 이어야 합니다."),
() -> assertTrue(study.getLimit() > 0, () -> "최대 참석인원은 0 명보다 커야합니다.")
); //람다식으로 3개의 assert문 실행결과 확인 가능
}
@Test
@Disabled //전체 클래스 테스트 수행시 동작하지 않도록 정의
void create2() {
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, ()-> new Study(-1));
assertEquals("Limit은 0보다 커야함.",exception.getMessage());
//해당 excpetion의 message가 기대하는 값과 같은지 확인
}
@Test
@DisplayName("생성 timeout 확인")
void create3() {
assertTimeout(Duration.ofSeconds(1), () -> new Study());
//1초안에 생성자 생성
assertTimeout(Duration.ofMillis(100), () -> {
new Study();
Thread.sleep(30000);
}); // 30000 millisecond 이후에 실패 처리
assertTimeoutPreemptively(Duration.ofMillis(100), () -> {
new Study();
Thread.sleep(3000);
}); // 100 millisecond가 지나면 바로 실패 처리
}
@Test
void create4() {
Study actual = new Study(10);
assertThat(actual.getLimit()).isGreaterThan(0); //3rd party assertjs
}
@BeforeAll //테스트를 실행하기 전에 딱 1번 반드시 static 메소드로만 사용가능. 리턴타입 없음.
static void BeforeAll() {
System.out.println("BeforeALL");
}
@AfterAll // 테스트를 실행한 이후 딱 1번만 수행(반드시 static 메소드로만 사용가능. 리턴타입 없음
static void AfterAll() { //모든 테스트가 실행된 이후에 1번만 실행
System.out.println("AfterAll");
}
@BeforeEach //각 테스트 수행 전 1번 실행
void BeforeEach() {
System.out.println("BeforeEach");
}
@AfterEach // 각 테스트 수행 후 1번 실행
void AfterEach() {
System.out.println("AfterEach");
}
}
condition에 따라서 테스트 실행
import org.junit.jupiter.api.*;
import java.time.Duration;
import java.util.function.Supplier;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
....
@Test
void conditionTest() {
assumeTrue("LOCAL".equalsIgnoreCase(System.getenv("TEST_ENV")));
//TEST_ENV라는 환경변수가 LOCAL인 경우에만 아래 테스트가 수행됨.
Study study = new Study();
assertNotNull(study);
}
@Test
void conditionTest2() {
String env = System.getenv("TEST_ENV");
//TEST_ENV라는 환경변수가 LOCAL인 경우에만 아래 테스트가 수행됨.
assumingThat(("LOCAL".equalsIgnoreCase(env)),()->{
System.out.println("succeed to test");
});
//TEST_ENV라는 환경변수가 LOCAL가 아닌 경우에만 아래 테스트가 수행됨.
assumingThat(!("LOCAL".equalsIgnoreCase(env)),()->{
System.out.println("Failed to test");
});
Study study = new Study();
assertNotNull(study);
}
@Test
@EnabledOnOs(OS.WINDOWS) //특정 OS에 특화된 테스트시 활용
@EnabledOnJre(JRE.JAVA_11) //자바 11버전에서만 실행
@EnabledIfEnvironmentVariable(named= "TEST_ENV", matches = "local") //환경변수 TEST_ENV가 local인 경우에만 실행
void conditionTest3() {
String env = System.getenv("TEST_ENV");
//TEST_ENV라는 환경변수가 LOCAL인 경우에만 아래 테스트가 수행됨.
assumingThat(("LOCAL".equalsIgnoreCase(env)),()->{
System.out.println(env);
});
//TEST_ENV라는 환경변수가 LOCAL가 아닌 경우에만 아래 테스트가 수행됨.
assumingThat(!("LOCAL".equalsIgnoreCase(env)),()->{
System.out.println(env);
});
Study study = new Study();
assertNotNull(study);
}
커스텀 테그
package hello.test;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
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
@Tag("slow")
public @interface SlowTest {
}
...........
//실제 사용 Test
@SlowTest
void conditionTest() {
String env = System.getenv("TEST_ENV");
assumeTrue("LOCAL".equalsIgnoreCase(env));
//TEST_ENV라는 환경변수가 LOCAL인 경우에만 아래 테스트가 수행됨.
assumingThat(("LOCAL".equalsIgnoreCase(env)),()->{
System.out.println("succeed to test");
});
assumingThat(!("LOCAL".equalsIgnoreCase(env)),()->{
System.out.println("succeed to test");
});
Study study = new Study();
assertNotNull(study);
}
테스트 반복 실행
package hello.test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.RepetitionInfo;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.aggregator.AggregateWith;
import org.junit.jupiter.params.aggregator.ArgumentsAccessor;
import org.junit.jupiter.params.aggregator.ArgumentsAggregationException;
import org.junit.jupiter.params.aggregator.ArgumentsAggregator;
import org.junit.jupiter.params.converter.ArgumentConversionException;
import org.junit.jupiter.params.converter.ConvertWith;
import org.junit.jupiter.params.converter.SimpleArgumentConverter;
import org.junit.jupiter.params.provider.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class OtherTest {
@RepeatedTest(10)
@DisplayName("반복 테스트1")
public void test1() {
System.out.println("repeat test");
}
@DisplayName("반복 테스트 2")
@RepeatedTest(value = 10, name= "{displayName},{currentRepetition}/{totalRepetitions}")
public void ParameterizedTest1(RepetitionInfo repetitionInfo) {
System.out.println("count:"+ repetitionInfo.getCurrentRepetition() +"total:"
+ repetitionInfo.getTotalRepetitions());
}
@DisplayName("파라미터 출력")
@ParameterizedTest(name = "{index} {displayName} message={0}")
@ValueSource(strings = {"1","2","3","4"})
@EmptySource
@NullSource
@NullAndEmptySource //empty와 null을 동시에 파라미터로 넘김
void ParameterizedTest2(String str) {
System.out.println(str);
}
@DisplayName("파라미터 출력1")
@ParameterizedTest(name = "{index} {displayName} message={0}")
@ValueSource(ints ={10, 20, 30})
void ParameterizedTest3(@ConvertWith(ArgumentConvert.class) Study study) {
System.out.println(study.getLimit());
}
@DisplayName("파라미터 출력2")
@ParameterizedTest(name = "{index} {displayName} message={0}")
@CsvSource({"10, '자바 테스트1'" ,"20, '파이썬 테스트1'"})
void ParameterizedTest4(Integer limit, String name) {
System.out.println(new Study(limit,name));
}
static class ArgumentConvert extends SimpleArgumentConverter { //1개의 argument에 사용
@Override
protected Object convert(Object source, Class<?> targetType) throws ArgumentConversionException {
assertEquals(Study.class, targetType,"can only covert to Study" );
return new Study(Integer.parseInt(source.toString()));
}
}
@DisplayName("파라미터 출력3")
@ParameterizedTest(name = "{index} {displayName} message={0}")
@CsvSource({"30, '자바 테스트2'" ,"40, '파이썬 테스트2'"})
void ParameterizedTest5(ArgumentsAccessor argumentsAccessor) {
System.out.println(new Study(argumentsAccessor.getInteger(0),argumentsAccessor.getString(1)));
}
@DisplayName("파라미터 출력4")
@ParameterizedTest(name = "{index} {displayName} message={0}")
@CsvSource({"50, '자바 테스트3'", "60, '파이썬 테스트3'"})
void ParameterizedTest6(@AggregateWith(Aggregator.class) Study study) {
System.out.println(study.getLimit()+" "+ study.getName());
System.out.println(study);
}
static class Aggregator implements ArgumentsAggregator {
@Override
public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) throws ArgumentsAggregationException {
Study study = new Study(accessor.getInteger(0),accessor.getString(1));
return study;
}
}
}
테스트 인스턴스
package hello.test;
import org.hibernate.resource.transaction.spi.DdlTransactionIsolator;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.RegisterExtension;
//@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
//@TestInstance(TestInstance.Lifecycle.PER_CLASS) //테스트클래스의 테스트메소드간 인스턴스 공유
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) //테스트 순서 지정
//@ExtendWith(TestExtension.class) // extension 을 선언적으로 등록하는 방법
public class InstanceTest {
int value = 1;
@RegisterExtension //extension 을 프로그래밍하여 등록하는 방법
static TestExtension testExtension = new TestExtension(500L);
@DisplayName("인스턴스 테스트")
@Test
@Order(2) //2번째로 실행
void instance_Test1() {
System.out.println("instance test1:" + value++);
}
@DisplayName("인스턴스 테스트")
@Test
@Order(1) //첫번째로 실행
@Disabled
void instance_Test2() {
System.out.println("instance test2:" + value++);
}
@Test
@Order(3) //세번째로 실행
void instance_Test3() {
System.out.println("instance test3:" + value);
}
@BeforeAll
void beforeAll() {
System.out.println("beforeAll");
}
@AfterAll
void afterAll() {
System.out.println("afterAll");
}
@Test
void create_new() {
try {
Thread.sleep(1005L);
System.out.println(this);
System.out.println("test");
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
}
Extension 클래스
package hello.test;
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import java.lang.reflect.Method;
public class TestExtension implements BeforeTestExecutionCallback, AfterTestExecutionCallback {
private long THRESHOLD;
public TestExtension(long THRESHOLD) {
this.THRESHOLD = THRESHOLD;
}
@Override
public void beforeTestExecution(ExtensionContext context) throws Exception {
ExtensionContext.Store store = getStore(context);
store.put("startTime", System.currentTimeMillis());
}
@Override
public void afterTestExecution(ExtensionContext context) throws Exception {
Method requiredTestMethod = context.getRequiredTestMethod();
SlowTest annotation = requiredTestMethod.getAnnotation(SlowTest.class);
String testMethodName = requiredTestMethod.getName();
ExtensionContext.Store store = getStore(context);
long start_time = store.remove("startTime", long.class);
long duration = System.currentTimeMillis() - start_time;
if (duration > THRESHOLD && annotation == null) {
System.out.printf("please consider mark method [%s] with @SlowTest.\n", testMethodName);
}
}
private ExtensionContext.Store getStore(ExtensionContext context) {
String testClassName = context.getRequiredTestClass().getName();
String testMethodName = context.getRequiredTestMethod().getName();
ExtensionContext.Store store = context.getStore(ExtensionContext.Namespace.create(testClassName, testMethodName));
return store;
}
}