|
TDD
assertEquals(예상값, 실제값);
assertEquals("설명", 예상값, 실제값);
TDD에서 중요한 점
- 목표 이미지를 미리 세운다.
- 자동화된 테스트 케이스를 작성한다.
- 만족하는 로직을 작성하고 정제한다.
보통 테스트에 사용할 자원이나 객체들을 준비해놓는 부분을 픽스처라고 부른다.
대부분의 테스트 프레임워크는 픽스처를 지원한다.
TDD 장점
- 개발의 방향을 잃지 않게 유지해준다.
- 품질 높은 소프트웨어 모듈로 만들어 준다.
- 자동화된 단위 테스트 케이스를 갖게 된다.
- 사용설명서 & 의사소통의 수단이 된다.
- 설계 개선하는데 도움이 된다.
로버트 마틴의 테스트 코드 작성법
- 실패하는 테스트를 작성하기 전에는 절대로 제품 코드를 작성하지 않는다.
- 실패하는 테스트 코드를 한 번에 하나 이상 작성하지 않는다.
- 현재 실패하고 있는 테스트를 통과하기에 충분한 정도를 넘어서는 제품 코드를 작성하지 않는다.
JUnit이 기본적으로 제공하는 기능은 아래와 같다.
- 테스트 결과가 예상과 같은지 판별해주는 단정문
- 여러 테스트에서 공용으로 사용할 수 있는 테스트 픽스처
- 테스트 작업을 수행할 수 있게 해주는 테스트 러너
assertSame([message], expected, actual)//두 객체가 정말 동일한 객체인지 주소값으로 비교하는 단정문
assertNotSame([message], expected, actual)
메세지 박스가 있는 경우는 캐시 기능을 만들었는데, 해당 캐시가 정확히 동작하는지 판단할 필요가 있는 경우에 사용한다.
cache.add(sameObject, KEY);
assertSame("캐시처리 실패", sameObject, cache.lookup(KEY));
비슷하게 싱글톤으로 만들어진 객체를 비교할 때에도 사용한다.
static public void assertSame(String message, Object expected, Object actual) {}
if (expected == actual) {
return;
}
failNotSame(message, expected, actual);
}
위 코드는 실제 assertSame
메소드의 구현 코드이다.
테스트 코드를 작성 중 완전히 작성하지 못한 경우 fail()
를 추가해두면 좋다.
Junit 4 특징
- Java5 어노테이션 지원
- 메소드 명이 test로 시작하지 않아도 된다.
- 좀 더 유연한 픽스처 제공
- @BeforeClass
- @AfterClass
- @Before
- @After
- 예외 테스트
- @Test(expected=NumberformatException.class)
- 시간 제한 테스트
- @Test(timeout=1000)
- 테스트 무시
- @Ignore(“This method isn’t working yet”)
- 배열 지원
- assertArrayEquals([message], expected, actual)
- @RunWith(클래스이름.class)
- JUnit Test 클래스를 실행하기 위한 러너를 명시적으로 지정한다.
- @RunWith는 junit.runner.Runner를 구현한 외부 클래스를 인자로 갖는다.
- @SuiteClasses(Class[])
- 보통 여러 개의 테스트 클래스를 수행하기 위해 쓰인다. @RunWith를 이용해 Suite.class를 러너로 사용한다.
- 파라미터를 이용한 테스트
@RunWith(Parameterized.class)
@Parameterspublic static Collection data() {
}
@SuiteClasses
Suite 클래스는 JUnit3에서의 static Test Suite() 메소드와 동일한 일을 수행한다.
하지만, JUnit4에서는 어노테이션을 통해 일괄적으로 테스트를 수행 할 수 있다.
@RunWith(Suite.Class)
@SuiteClasses(Atest.class, BTest.class, CTest.class)
public class ABCSuite {
}
Hamcrest 라이브러리
assertEquals 대신 assertThat이라는 구문을 사용하기를 권장한다.
assertThat(테스트 대상, matcher 구문);
assertThat("메시지", 테스트 대상, matcher 구문);
Junit 라이브러리 구조 자체에 대한 설명을 볼 수 있는 sourceforge-junit에서 패턴, 원리에 대해 설명한다.
Mock
Mock 객체란, 실제 객체를 만들어 테스트 하기에는 힘들어 가짜 객체를 만들어 사용하는 데 쓰이는 객체를 Mock 객체라고 한다.
언제 사용하는가 ?
- 환경 구축을 위한 작업 시간이 많이 필요한 경우에 Mcok 객체를 사용한다.
- 경우에 따라서는 특정 모듈을 아직 갖고 있지 않아서 테스트 환경을 구축하지 못할 수도 있을 때 사용한다.
- 타 부서와의 협의나 정책이 필요한 경우에도 Mock 객체가 필요하다.
- 테스트가 특정 경우나 순간적인 상황에 의존적일 경우
- 테스트 시간이 오래 걸릴 경우
테스트 더블
- 오리지널 객체를 사용해서 테스트를 진행하기가 어려울 경우 이를 대신해서 테스트를 진행할 수 있도록 만들어주는 객체를 지칭한다.
그러나 Mock이라는 단어를 더 많이 사용한다.
더미 객체
- 인스턴스화 될 수 있는 수준으로만 만든 가짜 껍데기를 말한다.
- 기능이 없으므로 더미 객체의 메소드 호출시 예외 발생을 추가하는 것도 방법이다.
테스트 스텁
- 더미 객체가 마치 실제로 동작하는 것처럼 보이게 만들어 놓은 객체
- 객체의 특정 상태를 가정해서 만들어 놓은 단순 구현체이다.
페이크 객체
- 복잡한 로직이나, 객체 내부에서 필요로 하는 다른 외부 객체들의 동작을 비교적 단순화 하여 구현한 객체이다.
- 결과적으로는 테스트 케이스 작성을 진행하기 위해 필요한 다른 객체들과의 의존성을 제거하기 위해 사용된다.
테스트 스파이
- 테스트에 사용 되는 객체에 대해서도, 특정 객체가 사용 됐는지, 그 객체의 예상 된 메소드가 정상적으로 호출 됐는지를 확인해야 하는 상황이 발생한다. 보통은 호출 여부를 몰래 감시해서 기록했다가
상태 기반 테스트 vs 행위 기반 테스트
상태 기반 테스트
- 특정한 메소드를 거친 후, 객체의 상태에 대해 예상 값과 비교하는 방식
행위 기반 테스트
-
리턴 값이 없거나 리턴 값이 있더라도 해당 값으로는 예상대로 동작 했는지에 대한 확인이 어려운 경우 활용
개발 영역에 따른 TDD 작성 패턴
생성자 테스트
- 단순히 클래스를 생성하는 생성자는 굳이 테스트 클래스를 작성 할 필요가 없다.
- 단, 객체서의 생성자의 의미뿐만 아니라 선행조건이나 업무로직을 직접 기술하는 경우도 있다.
DTO 스타일의 객체 테스트
특정한 목적을 갖고 만들어진 불변 객체의 경우에는 getter 메소드나 상태의 값을 확인할 수 있다.
TDD 유의사항
-
테스트 케이스는 이름이 중요하다.
testWithdraw_통장_잔고한계이상으로_인출요구시(){}
위처럼 한글 메소드명도 가능하므로 이해하기 쉬운 이름을 작명해야 한다.
제대로 동작하지 않는 테스트 케이스는 제거한다.
- TDD는 자동화 된 테스트를 만드는 것이 최종 목표가 아니다.
- 모든 상황에 대한 테스트 케이스를 만들 필요는 없다.
- 여러 개의 실패하는 테스트 케이스를 한 번에 만들지 않는다.
- 하나의 테스트 케이스는 하나만 테스트하도록 작성한다.
- 전통적인 테스트 기법을 배워두자.
- 테스트 케이스는 최대한 고립시킨다.
주의 사항
- 테스트 케이스는 무엇을 테스트하는 것인지 알 수 있어야 한다.
- Object Null check를 해야 한다.
- 캡슐화를 지켜야 한다.
- 한 번에 만들어지는 문자열을
+
대신StringBuilder
,StringBuffer
로 만들면 더 느릴 수 있다. - 테스트 항목과 테스트 내용을 맞추어야 한다.
- 불변객체를 의도했다면, 불변객체를 표시해주도록 한다.
- 코드에 순서가 필요하면 그것도 테스트한다.
'책 리뷰' 카테고리의 다른 글
[책] 그림으로배우는HTTP&NetworkBasic (0) | 2016.11.27 |
---|---|
[책] 오리지널스 - 애덤 그랜트 (0) | 2016.10.23 |
[책] 객체지향의 사실과 오해 - 조영호 지음 (1) | 2016.08.23 |
[책] 자바 8 인 액션 (0) | 2016.08.06 |
[책] 그래도 사랑 (0) | 2016.07.16 |