본문 바로가기
Framework/✔️JUnit5

TDD를 위한 JUnit5 사용법 2 - Assertion

by 발개발자 2022. 8. 15.
반응형

*Assertion

Assetion 테스트할 때 가장많이 사용되는 Class이다.

 

테스트할때 개발자가 의도한 값이 올바르게 출력되는지 확인시켜주는 다양한 Method가 존재한다.

 

먼저 Assertion에서 많이 사용되는 Method에 대해 araboza!

 

assertNotNull 값이 null 아닌지 확인
assertEquals 기대값과 실제값이 일치하는지 확인
assertTrue 조건이 (True)인지 확인
assertAll 모든 확인 구문 확인
assertThrows 예외 발생 확인
assertTimeout 특정 시간 안에 실행이 완료되는지 확인

 

위의 Assert 관련 메소드는 마지막에 실패했을 출력할 메시지 인자값을 추가해 줄수도 있다.

ex) assertNotNull(actualVal, 실패시 메시지); 이런식으로!

 

그렇다면 Method를 하나하나 사용해보자.

 

  • assertEquals

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class StudyTest {

	@Test
	@DisplayName("스터디 만들기 ")
	void create_new_study() {
		Study study = new Study();
		assertEquals(StudyStatus.DRAFT, study.getStatus(), "study를 처음 만들면 상태는 DRAFT여야 한다.");
	}

}

여기서 메시지를 위처럼 그냥 String형태로 바로 써서 넘겨주게 되면, 해당 테스트코드가 성공시에서 String 코드에 대한 연산을 실행한다.

따라서 단일 텍스트가 아니라, + String 계속 붙여서 쓰는 경우에는 불필요한 연산을 테스트마다 실행하게 된다.

 

이를 방지하기위해 아래와 같이 람다로 표현하면 테스트 실패시에만 String 연산을 하게 된다.

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class StudyTest {

	@Test
	@DisplayName("스터디 만들기 ")
	void create_new_study() {
		Study study = new Study();
		assertEquals(StudyStatus.DRAFT, study.getStatus(), ()->"study를 처음 만들면 상태는 DRAFT여야 한다.");
	}

}

 

  • assertTrue

 

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class StudyTest {

	@Test
	@DisplayName("스터디 만들기 ")
	void create_new_study() {
		Study study = new Study(-10);
		assertEquals(StudyStatus.DRAFT, study.getStatus(), ()->"study를 처음 만들면 "+ StudyStatus.DRAFT +"여야 한다.");
		assertTrue(study.getLimit() > 0, "스터디 참석인원은 0명보다 많아야 합니다.");
	}

}

 

해당 위의 코드라인에서 만약 테스트시 assetEquals 실패했다면 assertTrue까지 도달하지 못한다.

이럴 경우 모두 묶어서 테스트를 진행해주는게 assertAll이다.

 

  • assertAll

 

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class StudyTest {

	@Test
	@DisplayName("스터디 만들기 ")
	void create_new_study() {
		Study study = new Study(-10);
		assertAll(
				() -> assertNotNull(study),
				() -> assertEquals(StudyStatus.DRAFT, study.getStatus(), ()->"study를 처음 만들면 "+ StudyStatus.DRAFT +"여야 한다."),
				() -> assertTrue(study.getLimit() > 0, "스터디 참석인원은 0명보다 많아야 합니다.")
				);
	}

}

 

아래와 같이 assertAll Functional Interface Executable 인자로 받으므로 위와 같이 각각 람다로 표현해줘야 한다.

public static void assertAll(Executable... executables) throws MultipleFailuresError {
	AssertAll.assertAll(executables);
}

 

  • assertThrows

예외를 발생하기 위해 임시로 예외처리를 해주자.

public class Study {

	private StudyStatus status;// = StudyStatus.DRAFT;
	
	private int limit;
	
	public Study(int limit) {
		if(limit < 0) {
			throw new IllegalArgumentException("limit은 0보다 커야합니다!");
		}
		this.limit = limit;
	}
	
	
	public StudyStatus getStatus() {
		return this.status;
	}
	
	public int getLimit() {
		return this.limit;
	}
}

해당 Exception이 올바르게 처리가 된 모습니다.

 

또한 아래와 같이 Exception 메시지를 꺼내서 기대 값과 비교해 줄 수 있다.

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class StudyTest {

	@Test
	@DisplayName("스터디 만들기 ")
	void create_new_study() {
		IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> new Study(-1));
		String message = exception.getMessage();
		assertEquals("limit은 0보다 커야합니다!", message);
	}

}

 

 

  • assertTimeout

 

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class StudyTest {

	@Test
	@DisplayName("스터디 만들기 ")
	void create_new_study() {
		assertTimeout(Duration.ofSeconds(10), ()-> new Study(10));
	}

}

위와 같이 해당 기대한 시간안에 코드라인이 종료되면 성공하게 된다.

 

반대로 테스트 실패코드도 작성해보자.

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class StudyTest {

	@Test
	@DisplayName("스터디 만들기 ")
	void create_new_study() {
		assertTimeout(Duration.ofMillis(100), () -> {
			new Study(10);
			Thread.sleep(300);
		});
	}

}

만약 이렇게 기대한 시간보다 람다에서 진행되는 코드라인의 런타임이 더 오래 걸릴 경우, 테스트에서 런타임 코드라인을 다 기다리게 된다.

만약, 기대하는 시간보다 런타임 코드라인이 오래 걸리면 바로 테스트를 실패로 처리하고 종료하길 원한다면 아래와 같이  assertTimeoutPreemptively를 사용하면 된다.

 

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class StudyTest {

	@Test
	@DisplayName("스터디 만들기 ")
	void create_new_study() {
		assertTimeoutPreemptively(Duration.ofMillis(100), () -> {
			new Study(10);
			Thread.sleep(300);
		});
	}

}

 

Assertion에 대해 이 정도로 정리하고 마무리하자.

 

끗!

반응형

댓글