단정문
두 번째 테스트케이스를 생성한다.
com.hakademy.spring11.Test02
Copy package com . hakademy . spring11 ;
import org . junit . Test ;
public class Test02 {
@ Test
public void calculate () {
int a = 10 ;
int b = 20 ;
int c = 30 ;
System . out . println (a + b == c);
}
}
이 테스트케이스는 a와 b의 합계가 c와 같다는 것을 테스트하기 위해 작성했다.
이 테스트케이스를 실행하면 다음과 같은 결과가 나온다.
콘솔에 출력되는 값은 true
이며 테스트케이스가 성공했음을 알 수 있다.
위의 테스트케이스에서 c의 값을 수정하여 29로 변경해본다.
Copy package com . hakademy . spring11 ;
import org . junit . Test ;
public class Test02 {
@ Test
public void calculate () {
int a = 10 ;
int b = 20 ;
int c = 29 ;
System . out . println (a + b == c);
}
}
테스트 실행 결과는 다음과 같다.
a+b와 c가 같지 않으므로 콘솔에 false
가 나오지만 테스트는 여전히 성공으로 나오고 있다.
a+b와 c가 같으리라고 기대했을 수도 있고, 같지 않으리라 기대했을 수도 있겠지만 어떠한 상황을 기대했던 성공/실패 여부를 확인하기가 쉽지 않다.
즉, 내가 원하는 상황이 나오면 성공, 내가 원하지 않는 상황이 나오면 실패로 처리할 수 있어야 하며 이럴 때 JUnit에서 제공하는 단정문을 사용하면 쉽게 처리가 가능하다.
com.hakademy.spring11.Test03
Copy package com . hakademy . spring11 ;
import org . junit . Test ;
import junit . framework . Assert ;
public class Test03 {
@ Test
public void calculate () {
int a = 10 ;
int b = 20 ;
int c = 30 ;
Assert . assertEquals (a + b , c);
}
}
실행하면 다음과 같이 성공 화면이 나온다.
값을 변경하여 실행해보면 다른 결과가 나온다는 것을 알 수 있다.
Copy package com . hakademy . spring11 ;
import org . junit . Test ;
import junit . framework . Assert ;
public class Test03 {
@ Test
public void calculate () {
int a = 10 ;
int b = 20 ;
int c = 29 ;
Assert . assertEquals (a + b , c);
}
}
결과가 실패로 나오기 때문에 내가 원하는 상황이 나오지 않았음을 알 수 있다.
이렇게 단정문을 사용하면 테스트 결과를 조금 더 이해하기 쉽게 만들 수 있다.
Assert.assertEquals(a + b, c);
의 형태로 사용할 경우 Deprecated 표시가 나오는데 테스트케이스에서는 JUnit 관련 기능들을 좀 더 쉽게 쓸 수 있도록 static import를 권장하고 있다.
Copy import static org . junit . Assert . assertEquals ;
Copy assertEquals(a + b , c) ;
자동완성을 이용하면 조금 더 쉽게 구문을 완성할 수 있다.
단정문의 종류
JUnit의 단정문 종류는 다음과 같다.
assertEquals
assertEquals는 두 객체가 동등함을 단정하기 위한 구문이다.
Copy assertEquals([메시지] , 기대값 , 실제값)
메시지의 경우 실패시 표시될 내용이며 생략이 가능하다.
주의 : "동일"이 아닌 "동등"이기 때문에 자바의 equals와 같은 형태이다.
assertNotEquals
assertEquals의 반대인 두 객체가 동등하지 않음을 단정하기 위한 구문이다.
Copy assertNotEquals([메시지], 기대값, 실제값)
assertArrayEquals
assertArrayEquals는 두 배열이 동등함을 단정하기 위한 구문이다.
Copy assertArraysEquals([메시지], 기대배열, 실제배열)
assertSame
assertSame은 두 객체가 동일함을 단정하기 위한 구문이다.
Copy assertSame([메시지], 기대값, 실제값)
주의 : assertSame은 "동일" 비교이기 때문에 == 와 같은 형태이다.
assertNotSame
assertSame의 반대인 두 객체가 동일하지 않음을 단정하기 위한 구문이다.
Copy assertNotSame([메시지], 기대값, 실제값)
assertNull
assertNull은 대상 객체가 null임을 단정하기 위한 구문이다.
Copy assertNull([메시지], 객체)
assertNotNull
assertNull과 반대로 대상 객체가 null이 아님을 단정하기 위한 구문이다.
Copy assertNotNull([메시지], 객체)
assertTrue
assertTrue는 해당 결과가 true임을 단정하기 위한 구문이다.
일반적으로 값 자리에 논리식을 작성하여 검증한다.
assertFalse
assertFalse는 해당 결과가 false임을 단정하기 위한 구문이다.
Copy assertFalse([메시지], 값)
일반적으로 값 자리에 논리식을 작성하여 검증한다.
assertThat
assertThat은 다양한 상황을 단정하기 위한 구문이다.
Copy assertThat([메시지], 실제값, Matcher)
Matcher란 다양한 상황을 검증하기 위해 제공되는 명령 집합을 의미한다.
JUnit에서는 다양한 Matcher를 지원한다.
예를 들어 다음 구문은 같은 상황을 단정한다.
Copy assertTrue( 10 + 20 == 30 ) ;
assertEquals( 30 , 10 + 20 ) ;
assertThat( 10 + 20 , is( 30 )) ;
위의 구문에서 is()가 Matcher이며, 이와 같은 Matcher들은 다음 종류들이 존재한다.
allOf : 내부에 선언된 모든 Matcher가 정상일 경우 통과
anyOf : 내부에 선언된 Mathcer중 1개 이상 정상일 경우 통과
both : and로 연결된 두 Matcher가 모두 정상일 경우 통과
either : or로 연결된 두 Matcher중 1개
everyItem : 배열 or 리스트 요소를 순회하며 검사하여 모두 정상일 경우 통과
is : 비교하거나, 다른 Matcher와 조합할 때 사용
isA : 타입 검사를 수행하여 정상일 경우 통과
hasItem : 배열에서 Matcher에서 요구하는 값이 1개 이상일 경우 통과
hasItems : 배열에서 Matcher에서 요구하는 값들이 모두 1개 이상 있을 경우 통과
equalsTo : 값을 비교하여 같을 경우 통과
not : 단독으로 사용할 경우 같지 않음을 검사, is와 결합하여 부정할 때도 사용
nullValue : 비교값이 null일 경우 통과
notNullValue : 비교값이 null이 아닐 경우 통과
sameInstance : 비교값이 동일한 인스턴스일 경우 통과
theInstance : sameInstance와 동일
containsString : 대상에 특정 문자열이 포함되어 있을 경우 통과
startsWith : 대상이 특정 문자열로 시작할 경우 통과
endsWith : 대상이 특정 문자열로 종료할 경우 통과
직접 정의 : 내가 원하는 검사 방식을 직접 구현
작성 예시
Copy package com . hakademy . spring11 ;
import static org . hamcrest . CoreMatchers . everyItem ;
import static org . hamcrest . CoreMatchers . hasItem ;
import static org . hamcrest . CoreMatchers . hasItems ;
import static org . junit . Assert . assertThat ;
import java . util . Arrays ;
import java . util . List ;
import org . hamcrest . Description ;
import org . hamcrest . Matcher ;
import org . hamcrest . TypeSafeMatcher ;
import org . junit . Test ;
/**
* AssertThat 다루기
* @author Hakademy
*/
public class Test04 {
@ Test
public void test () {
int a = 10 , b = 20 , c = 30 ;
// 1. a + b가 c와 같다고 단정
// assertThat(a + b, is(c));
// 2. a + b가 int 형태라고 단정
// assertThat(a + b, isA(int.class));
// 3. 1과 2를 모두 만족한다고 단정
// assertThat(a + b, allOf(is(c), isA(int.class)));
// 4. 1과 2중 1개 이상 만족한다고 단정
// assertThat(a + b, anyOf(is(c), isA(int.class)));
// 5. 1과 2를 모두 만족한다고 단정
// assertThat(a + b, both(is(c)).and(isA(int.class)));
// 6. 1과 2중 1개 이상 만족한다고 단정
// assertThat(a + b, either(is(c)).or(isA(int.class)));
// 7. a + b가 c와 같지 않다고 단정
// assertThat(a + b, is(not(c)));
// 8. a + b가 null이라고 단정
// assertNull(a + b);
// assertThat(a + b, is(nullValue()));
// 9. a + b가 not null이라고 단정
// assertNotNull(a + b);
// assertThat(a + b, is(notNullValue()));
String str = "junit test framework" ;
// 10. str에 "frame"이 있다고 단정
// assertThat(str, containsString("frame"));
// 11. str이 "junit"으로 시작한다고 단정
// assertThat(str, startsWith("junit"));
// 12. str이 "work"로 종료한다고 단정
// assertThat(str, endsWith("work"));
// 13. 직접 정의한 Matcher 사용하기
// a + b가 짝수라고 단정
// assertThat(a + b, even());
List < Integer > list = Arrays . asList ( 1 , 2 , 3 , 4 , 5 );
// 14. list의 모든 구성요소가 int 형태라고 단정
// assertThat(list, everyItem(isA(int.class)));
// 15. list의 모든 구성요소가 짝수라고 단정
// assertThat(list, everyItem(even()));
// 16. list의 구성요소중 짝수가 존재한다고 단정
// assertThat(list, hasItem(even()));
// 17. list의 구성요소 중 1, 3이 존재한다고 단정
// assertThat(list, hasItems(1, 3));
// 18. list의 구성요소 중 5, 7이 존재한다고 단정
// assertThat(list, hasItems(5, 7));
}
// 사용자 정의 Matcher
public Matcher < Integer > even (){
return new TypeSafeMatcher < Integer >() {
@ Override
public void describeTo ( Description description) {
description . appendText ( "짝수 검증" );
}
@ Override
protected boolean matchesSafely ( Integer item) {
return item % 2 == 0 ;
}
};
}
}