3. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20장에서 다룰 내용
‘왜’ 테스트 하기 어려운가?
• 테스트를 작성하기 어려운 경우
• ‘테스트 악취’
1. 불분명, 불안정한 테스트
2. 테스트하기 어려운 코드
4. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21장에서 다룰 내용
읽기 쉬운
테스트 작성 가이드
5. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22장에서 다룰 내용
테스트를 위해 필요한 객체를 생성하고 싶을때마다
우리는 생성자 인자를 모두 직접 작성해야 한다.
- 또 이 객체를 생성하는 코드가 많아지면 테스트를
읽기 매우 어려워진다.
- 생성자 인자나 구조를 변경하는 순간 여러 테스트
가 깨지게 된다.
이 문제를 해결해서 복잡한 내용을 담은 테스트 코드
를 읽기 쉽게 만들어야 한다.
6. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
23장에서 다룰 내용
• 테스트가 실패하면 어디서 왜 테스트가 실패했는지 알 수 있게 쓰자.
7. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
테스트 실패! 제품 정상 동작 실패
테스트 성공! 제품 정상 동작
테스트 결과만 보고도 제품 동작이 보였으면
테스트에 기대하는 것 1
8. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
테스트에 기대하는 것 2
테스트만 보고도 제품의 문제점이 도출 되어야 함
실패 메시지가 매우 구체적이고 읽기 편해야 함.
If, 테스트 실패에도 어디가 문제인지 찾을 수 없다면
높은 가능성으로, 테스트를 지울 것이다.
9. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
테스트 잘 작성하기 1
• 이름 잘 짓기
10. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
테스트 잘 작성하기 2
단정에 이름 부여하기
assertEquals(16301, customer.getBalance());
assertEquals(“user balance”, 16301, customer.getBalance());
11. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
테스트 잘 작성하기 3
Matcher 를 사용하기
매쳐의 장점
1. 코드가 의도를 표현한다
2. 실패시 좋은 메시지를 보여준다
12. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
테스트 잘 작성하기 4
Date namedDate(long timeValue, final String name){
return new Date(timeValue) {
public String toString() { return name; }
}
}
객체에 자가 서술 추가하기 => 실패 메시지에 이름 출력
13. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
테스트 잘 작성하기 5
한 눈에 알아볼 수 있는 값으로 비교하기
Integer.MAX_VALUE, -1 …
14. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
테스트 잘 작성하기 6
jMock 객체에 이름 부여하기
final LineItem item1 = context.mock(LineItem.class,”item1”);
15. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
테스트 실패! 제품 정상 동작 실패
테스트 성공! 제품 정상 동작
테스트 결과만 보고도 제품 동작이 보였으면
테스트에 기대하는 것
16. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
23장
If, 테스트가 실패하면
어디가 / 어떻게 / 얼만큼 왜 틀렸는지 자세하게 표현해야 한다.
자세하게 표현하는 방법을 몇 가지를 안내함.
테스트만 보고도 제품의 문제점이 도출 되어야 함
17. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
24장에서 다룰 내용
목표 : 회복력 있는 테스트 작성하기
- jUnit, Hamcrest, jMock으로 검사문을 잘 작성하자
- 재사용성이 뛰어나게 작성하기
- 예상문으로 검사하는 법 (jMock 사용법)
18. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
1. Null을 전달하지 않는다.
public static final Customer NO_CUSTOMER_FOUND = null;
Maybe<Customer> NO_CUSTOMER_FOUND = Maybe.nothing()
Maybe 인터페이스 요구사항
1. 해당 객체를 하나를 넣고 받을 수 있어야 한다.
2. 객체가 비어있는 상태를 null 말고 표현해야 한다.
19. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
2. 단정문 활용하기
assertEquals(“price”, 92, instrument.getStrikePrice());
- 입력값이 바뀌면? 값을 계산하는 이율이 바뀌면?
assertThat(instrument.getTransactionId(),
largerThan(PREVIOUS_TRANSACTION_ID)
- 트랜잭션 ID가 늘어나더라도 테스트 실패하지 않음.
- 실패시 메시지를 훨씬 더 잘 표현함.
20. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
2-1. 문자열 단정하기
assertEquals(“err msg”, “price=92, id=FGD.430 request item is expired”, failureMessage);
- 출력 형식에 유연하지 않은 테스트
assertThat(failureMessage,
allOf(containsString(“strikePrice=92”),
containsString(“id=FGD.430”),
containsString(“is expired”));
- 다른 메시지가 추가될 수 있음.
- 출력 순서에 유연한 단정문
21. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
3. 예상문 작성하기
assertThat(failureMessage,
allOf(containsString(“strikePrice=92”),
containsString(“id=FGD.430”),
containsString(“is expired”));
oneOf(auditTrail).recordFailure(with(
allOf(containsString(“strikePrice=92”),
containsString(“id=FGD.430”),
containsString(“is expired”));
- 단정문은 예상문으로 확장할 수 있음
22. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
jMock 호출 순서 조절하기
oneOf(searchListener).searchMatched(ACTION1);
oneOf(searchListener).searchFinished();
만약, searchFinished가 먼저 호출 되고 searchMatched가 호출되면?
- 테스트 실패 했으면 좋겠다.
호출 순서가 바뀌어도
테스트가 성공한다!
23. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
jMock 호출 순서 조절하기 - Sequence
Sequence events = context.sequence(“events”);
oneOf(searchListener).searchMatched(ACTION1); inSequence(events);
oneOf(searchListener).searchMatched(ACTION2); inSequence(events);
oneOf(searchListener).searchFinished(); inSequence(events);
테스트 - searchFinished는 match 함수 이후에 호출 되어야 한다.
(단, action1과 action2는 순서가 보존되어야 한다.)
24. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
jMock 호출 순서 조절하기 - States
States searching = context.states(“searching”);
oneOf(searchListener).searchMatched(ACTION1);
oneOf(searchListener).searchMatched(ACTION2);
oneOf(searchListener).searchFinished();
테스트 – 두 함수 호출 상태를 관리한다.
when(searching.isNot(“finished”);
when(searching.isNot(“finished”);
then(searching.is(“finished”));
25. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
jMock 호출 순서 조절로 테스트 구성하기
allowing(searchListener).isReady(); will(returnValue(true));
then(listenerState.is(“ready”);
oneOf(searchListener).searchMatched(ACTION1));
when(listenerState.is(“ready”);
searchListener.isReady() 함수가 호출되어(allowing) true를 반환하면,
searchListener.searchMatched(ACTION)이 호출되어야 한다.
26. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
24장
• jMock 사용법
• http://www.jmock.org/getting-started.html
• jMock vs EasyMock
• http://jeantessier.com/SoftwareEngineering/Mocking.html#jMock
27. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
25장에서 다룰 내용
목표 : 데이터베이스 테스트하기
- ORM 테스트 하기
- 데이터베이트 테스트에 주의해야할 점
29. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
데이터베이스 테스트를 하기 전에…
테스트 준비/정리 과정 중 데이터베이스 내용을 지우는 것은 언제?
• 기존 테스트
프로세스 메모리에만 영향
새로 실행할 때마다 항상 초기화 됨
• DB 테스트
테스트 실행 후 기억 장치에 영향을 줌
다음 실행할 때 기억 장치에 영향 받음
30. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
정답 - 데이터베이스 테스트 전
• 준비 과정에서 데이터베이스를 지우자
1. 필요한 초기화를 테스트에 나타낼 수 있다.
이 테스트에 필요한 데이터베이스가 가시적으로 보인다
2. 테스트가 끝나고 결과를 열어볼 수 있다.
테스트 후에 결과를 열어볼 수 있다.
테스트 간에 영향을 주는 것들을 격리할 필요가 있다.
31. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
트랜잭션 테스트
데이터베이스에 삽입/조회 테스트 작성하기
32. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
1. 트랜잭션 열기
2. 정의한 동작 실행
3. 커밋 시도
4. 트랜잭션 실패시 롤백
DB에 추가할 동작 정의
33. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
1. 데이터 list 받아옴
2. 데이터 객체를 만들어서
데이터베이스에 추가함.
3. 데이터베이스에 데이터 추가 완료
정리한 조건에 따라 데이터를
얻을 수 있는지 확인한다
34. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
트랜잭션 테스트
1. 트랜잭션을 관리하는 객체
2. DB에 전달할 동작을 전달하는 인터페이스
3. 값 객체를 생성하여 인터페이스에 동작을 정의하
여 객체를 실행시킨다.
DB 연산에 대한 테스트를 작성하는 골격
35. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
ORM 왕복 테스트
데이터베이스와 상호작용하는 객체는 정상적으로 동작하는가?
36. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
ORM 왕복 테스트
테스트 하고자 하는 대상 – DB와 데이터를 주고받을 객체
- 테스트 의도 : 객체 프로퍼티가 DB에 반영이 되나?
37. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
ORM 왕복 테스트
객체 DB
멤버 : Train_ID, Train_type, Max_speed
필드 Train_ID, Train_type, Max_speed
38. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
ORM 왕복 테스트
1. Train_ID 선택
2. Train_ID 엔티티 확인
3. Train_ID가 저장 가능
한지 확인
검증대상 : Train_ID
23
39. s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
데이터베이스를 거친 테스트는 항상 느리다!
메모리 내부
단위
테스트
외부 프로세스
통합
테스트
외부 서비스
통합
테스트
테스트의 4단계로는 준비, 실행, 단정(검사, 예상), 정리
테스트의 이름을 작성하는 법
햄크래스트 매쳐를 이용해서 테스트 코드를 작성하는 법
22장에서는 매우 중요한 내용을 다뤘는데 바로 builder
값을 가진 객체를 많이 만드려면 꼭 필요함
23장에서 다룰 내용은 테스트가 우리가 원하는 테스트로서 구성되게 하려고 합니다.
우리가 테스트 코드에게 어떤것을 기대하는지 생각해보고, 기대한 바를 이룰 수 있도록 가이드하는 장입니다.
제품의 오류 발생과 테스트 실패가 같아야 한다. ( 제품 오류 발생과 테스트 실패가 역관계가 아니라 대우 관계를 확보)
문자열 매칭도 좋지만 중요한 것은 절대로 문자열 전체를 비교하지 말라는 것. 안티패턴을 보여주고 있다.
isReady 함수의 결과가 true가 아니라면?
searchMatched 함수가 호출이 되지 않는다면?