SlideShare une entreprise Scribd logo
1  sur  28
Télécharger pour lire hors ligne
Effective Unit Testing
테스트 더블
최용은
테스트 더블
“테스트 더블”은 무엇인가?
테스트하려는 코드를 주변에서 분리하게 도와 주는
놈!
또는
테스트 작성 시 테스트 대상 코드와 상호작용하는
객체
테스트 대상 코드와 협력 객체를 분리
출처 : Effective Unit Testing
테스트 더블의 위력!
● 테스트 대상 코드를 격리한다.
● 테스트 속도를 개선한다.
● 예측 불가능한 실행 요소를 제거한다.
● 특수한 상황을 시뮬레이션한다.
● 감춰진 정보를 얻어낸다.
예) 테스트 대상코드(Car)와 협력 객체(Engine과 Rout)
public class Car {
private Engine engine;
public Car(Engine engine) { this.engine = engine;}
public void start() { engine.start(); }
public void drive(Route route) {
for(Directions directions : route.directions()){
directions.follow();
}
}
public void stop(){ engine.stop(); }
}
테스트 대상 코드를 격리한다.
● Car는 Engine과 Route를 직접 사용하지만, Directions는 Route를 통해 간접적으로
만 사용
● 즉, 협력 객체로 부터 Car를 격리하는 일은 Engine과 Route만 테스트 더블로 교체.
출처 : Effective Unit Testing
출처 : Effective Unit Testing
테스트 속도를 개선한다.
● 만약 Car가 이동할 최단경로를 구할 때 Route가 가중 그래프 검색 알
고리즘을 이용한다면 ?
○ 알고리즘을 계산하느라, 속도가 느려짐
● 테스트 더블을 이용해서 사전에 계산해둔 경로를 반환 한다면?
○ 테스트는 눈부시게 빨리짐!
예측 불가능한 실행 요소를 제거한다.
public class Route {
private Clock clock = new Clock();
private ShortestPath algorithm = new …();
public Collection<Directions> directions() {
if(clock.isRushHour()) {
return algorithm.avoidBusyIntersections();
}
return algorithm.calculateRouteBetween(...);
}
}
혼잡한 시간에는 경로 계산
결과가 달라진다!
● 비결정적인 요인을 다룰땐, 테스트 더블!
○ 항상 똑같은 시간을 알려주는 테스트 더블로 변경!
특수한 상황을 시뮬레이션한다.
● Route가 Directions를 구할 때 구글 맵스를 이용한다고 가정 해보자.
○ 목적지까지 경로를 요청하는 도중 인터넷이 끊긴 경우 Route는
잘 대처하는지 어떡해 확인 할 수 있을까?
연결 요청을 처리하는 부분을 테스트 더블로 대체해서 예외 발생시키자!
감춰진 정보를 얻어낸다.
● 시나리오
○ 누군가 Car의 시동을 걸면 Car는 Engine을 가동한다.
○ 이 동작이 실제로 일어났는지 어떻게 확인 할 수 있을
까?
● 역시 테스트 더블이 해결책!
감춰진 정보를 얻어낸다.
public class CarTest {
@Test public void engineIsStartedWhenCarStarts() {
TestEngine engine = new TestEngine();
new Car(engine).start();
assertTrue(engine.isRunning());
}
}
public class TestEngine extends Engine {
private boolean isRunning;
public void start(){isRunning = true;}
public boolean isRunning(){return isRunning;}
}
테스트 더블의 종류
테스트 더블
테스트 스텁 가짜 객체 테스트 스파이 Mock 객체
테스트 스텁 - 유난히 짧다.
● 스텁의 사전적 정의
○ 스텁 (명사) 끝이 잘렸거나 유난히 짧은 것
● 테스트 스텁의 목적은 원래의 구현을 최대한 단순한 것으로 대체 하는 것
스텁의 전형적인 모습! ( 아.무.것.도.하.지.않.아.요 )
public class LoggerStub implements Logger {
public void log(LogLevel level, String message) { }
}
테스트 스텁 - 유난히 짧다.
public class LoggerStub implements Logger {
public void log(LogLevel level, String message) { // 여전히 아무 일도 하지 않는다. }
public LogLevel getLogLevel() {
return LogLevel.WARN; // 하드코딩된 값을 반환한다.
}
}
LogLevel을 반환하는 메서드 정의
스텁을 사용하는 세 가지 이유
1. 테스트는 대상 코드가 로깅하는 내용에는 전혀 관심 없다.
2. 가동 중인 로그 서버가 없으니 로깅은 어차피 실패했을 거다.
3. 테스트 스위트가 콘솔로 대량의 정보를 쏟아내는 건 바라지 않는다. (파일에 쓰는 건 별로 상관없다.)
가짜 객체 - 뒤끝 없이 처리한다.
● 언제 사용?
○ 최소한의 행동을 취해주거나 입력값에 따라 다르게 행동 할때 사용!
● 왜 사용?
○ 진짜 객체를 사용할때 생기는 부수효과나 연쇄동작이 일어나지 않게 경
량화 및 최적화 한 것
가짜 객체 - 뒤끝 없이 처리한다.
public class FakeUserRepository implements UserRepository {
private Collection<User> users = …. // 인메모리 데이터베이스
public void save(User user){
if( findById(user.getId()==null ) { users.add(user); }
}
public User findById(long id) {
for( User user : users ) {
if( user.getId() == id ) return user;
}
return null;
}
}
public interface UserRepository {
void save(User user);
User findById(long id);
}
테스트 스파이 - 기밀을 훔친다.
● 언제 사용?
○ 입력 인자로 사용되는 객체가 테스트에 필요한 정보를 알려주는 API를 제
공하지 않을 때 유용
○ 구현 어디에도 전달된 메시지가 잘 기록되었는지 알려주는 메서드가 보이
지 않을 시
주의 : 테스트 스파이를 사용해야 하는 상황이 발생하면 설계가 제대로 되었는지 한번쯤 의심을 ;ㅁ;
테스트 스파이 - 기밀을 훔친다.
코드 - 테스트에 필요한 정보를 제공하지 않아 테스트 스파이가 필요한 상황
public class DLog{
private final DLogTarget[] targets;
public DLog(DLogTarget… targets) {
this.targets = targets;
}
public void write(Level level, String message) {
for (DlogTarget each : targets) {
each.write(level, message);
}
}
}
public interface DLogTarget {
void write(Level level, String message);
}
테스트 스파이 - 기밀을 훔친다.
public class DLogTest{
@Test public void writeEachMessage…() {
SpyTarget spy = new SpyTarget();
DLog log = new DLog(spy);
log.write(Level.INFO, “message”);
assertTrue(spy.received(Level.INFO, “message”);
}
private class SpyTarget implements DLogTarget {
private List<String> log = ….;
public void write(Level level, String message) {
log.add(concatenated(level, message));
}
boolean received(Level level, String message) {
return log.contains(concatenated(level, message));
}
private String concatenated(Level level, String message){
return level.getName() + “: “ + message;
}
}
}
코드 - 간단히 구현해본 테스트 스파이
Mock 객체 - 예기치 않은 일을 막아준다.
● 특정 조건이 발생하면 미리 약속된 행동을 취하고, 약속된 행동이 취해지지 않으면 바
로 테스트 실패가 된다.
○ 예
■ UserRespository 으로 설명 하자면, findById()의 파라미터로 123을 주면
null, 124를 주면 가짜 user객체를 반환하는 식이다.
● 메서드를 파라미터에 따라 다르게 처리하게 한 스텁 수준 이지만, 이게
다가 아니다.
■ 하지만 123,124 외에 인자를 넘겼거나 다른 메서드를 호출하면 테스트를
실패하게 만들 수 있다.
● 이전 보다(스텁,가짜,스파이) 훨씬 정교한 테스트를 만들 수 있다.
○ 메서드가 호출되었는지? 몇번 호출되었는지 확인 할 수 있다.
Mock 객체 - 예기치 않은 일을 막아준다.
● Mock 객체 라이브러리
○ Mockito
○ JMock
○ EasyMock
Mock 객체 - 예기치 않은 일을 막아준다.
public class TestTranslator {
@Test public void userInternetForTranslation() {
//given
final Internet internet = mock(Internet.class);
given(internet.get(with(containsString(“langpair=en%7Cfi”)))
.willReturn(returnValue(“{“translatedText”:”kukka”}”));
//when
Translator t = new Translator(internet);
String translation = t.translate(“flower”, ENGLISH, FINNISH);
//then
assertEquals(“kukka”, translation);
}
}
테스트 더블 활용 지침
● 용도에 맞는 도구를 꺼내 써라
● 준비하고, 시작하고, 단언하라
● 구현이 아니라 동작을 확인하라
● 자신의 도구를 선택해라
● 종속 객체를 주입하라
용도에 맞는 더블을 선택해라.
● “가독성” - 테스트를 가장 읽기 쉽게 만들어주는 선택
● 그 외
○ 두 객체 간 상호작용의 결과로 특정메서드가 호출되었는지 확인하고 싶다면 Mock 객체
○ …...
○ 이도 저도 아니라면 동전을 던져보자, 앞면 Mock, 뒷면 스텁
용도에 맞는 더블을 선택해라.
● 결론
○ 스텁은 질문하고 Mock은 행동한다.
구현이 아니라 동작을 확인하라.
● 검증 목적과 관련 없는 지극히 사소한 변경마저도 테스트 실패 한다면..
○ 못질을 너무 많이 해서 구멍이 송송 뚫린 불쌍한 목판처럼 되어 버린다.
● 테스트는 오직 한 가지만 검사해야 하고 그 의도를 명확히 전달하도록 작성되어야 한
다.
● 핵심
○ “구현이 아니라 동작을 검증 하자!”
종속 객체를 주입하라
● 진짜 객체를 테스트 더블 객체로 교체할 수 있어야 한다. 교체할 수
없다면 단위 테스트 작성도 못한다.
○ 종속 객체를 private 필드에 저장하거나 팩토리 메서드 등을 통
해 외부로부터 얻도록 해야 함
○ 보통 생성자 주입 방식을 많이 애용 함
Thank U

Contenu connexe

Tendances

Effective Unit Testing
Effective Unit TestingEffective Unit Testing
Effective Unit TestingYeon Soo Kim
 
예외처리가이드
예외처리가이드예외처리가이드
예외처리가이드도형 임
 
목 오브젝트(Mock Object)의 이해
목 오브젝트(Mock Object)의 이해목 오브젝트(Mock Object)의 이해
목 오브젝트(Mock Object)의 이해Yong Hoon Kim
 
TDD&Refactoring Day 03: TDD
TDD&Refactoring Day 03: TDDTDD&Refactoring Day 03: TDD
TDD&Refactoring Day 03: TDDSuwon Chae
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven DevelopmentChangHyeon Bae
 
Introduce Katalon tool
Introduce Katalon toolIntroduce Katalon tool
Introduce Katalon tool재연 김
 
Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Ryan Park
 
Tdd live spring camp 2013
Tdd live spring camp 2013Tdd live spring camp 2013
Tdd live spring camp 2013beom kyun choi
 
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드 Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드 SangIn Choung
 
Io t에서의 소프트웨어단위테스트_접근사례
Io t에서의 소프트웨어단위테스트_접근사례Io t에서의 소프트웨어단위테스트_접근사례
Io t에서의 소프트웨어단위테스트_접근사례SangIn Choung
 
[2011 04 11]mock_object 소개
[2011 04 11]mock_object 소개[2011 04 11]mock_object 소개
[2011 04 11]mock_object 소개Jong Pil Won
 
오버라이딩을 사용한 테스트 시의 설정 처리
오버라이딩을 사용한 테스트 시의 설정 처리오버라이딩을 사용한 테스트 시의 설정 처리
오버라이딩을 사용한 테스트 시의 설정 처리도형 임
 
C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기OnGameServer
 
자바 테스트 자동화
자바 테스트 자동화자바 테스트 자동화
자바 테스트 자동화Sungchul Park
 

Tendances (19)

Effective Unit Testing
Effective Unit TestingEffective Unit Testing
Effective Unit Testing
 
TDD with JUnit 2
TDD with JUnit 2TDD with JUnit 2
TDD with JUnit 2
 
예외처리가이드
예외처리가이드예외처리가이드
예외처리가이드
 
목 오브젝트(Mock Object)의 이해
목 오브젝트(Mock Object)의 이해목 오브젝트(Mock Object)의 이해
목 오브젝트(Mock Object)의 이해
 
Unit Test With J Unit
Unit Test With J UnitUnit Test With J Unit
Unit Test With J Unit
 
TDD&Refactoring Day 03: TDD
TDD&Refactoring Day 03: TDDTDD&Refactoring Day 03: TDD
TDD&Refactoring Day 03: TDD
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven Development
 
Introduce Katalon tool
Introduce Katalon toolIntroduce Katalon tool
Introduce Katalon tool
 
Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005
 
Tdd live spring camp 2013
Tdd live spring camp 2013Tdd live spring camp 2013
Tdd live spring camp 2013
 
Exception&log
Exception&logException&log
Exception&log
 
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드 Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
 
Io t에서의 소프트웨어단위테스트_접근사례
Io t에서의 소프트웨어단위테스트_접근사례Io t에서의 소프트웨어단위테스트_접근사례
Io t에서의 소프트웨어단위테스트_접근사례
 
TEST?
TEST?TEST?
TEST?
 
[2011 04 11]mock_object 소개
[2011 04 11]mock_object 소개[2011 04 11]mock_object 소개
[2011 04 11]mock_object 소개
 
오버라이딩을 사용한 테스트 시의 설정 처리
오버라이딩을 사용한 테스트 시의 설정 처리오버라이딩을 사용한 테스트 시의 설정 처리
오버라이딩을 사용한 테스트 시의 설정 처리
 
C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기
 
X unit 14장
X unit 14장X unit 14장
X unit 14장
 
자바 테스트 자동화
자바 테스트 자동화자바 테스트 자동화
자바 테스트 자동화
 

En vedette

Commit Log in English
Commit Log in EnglishCommit Log in English
Commit Log in English正之 安宅
 
Estrategias de enseñanza
Estrategias de enseñanzaEstrategias de enseñanza
Estrategias de enseñanzaIsabo Fierro
 
La historia del curriculum
La historia del curriculumLa historia del curriculum
La historia del curriculumIsabo Fierro
 
La noción del medio
La noción del medioLa noción del medio
La noción del medioIsabo Fierro
 
El conflicto sobre la educación
El conflicto sobre la educaciónEl conflicto sobre la educación
El conflicto sobre la educaciónIsabo Fierro
 
La competencia como organizadora
La competencia como organizadoraLa competencia como organizadora
La competencia como organizadoraIsabo Fierro
 
A presentation to show different types of camera
A presentation to show different types of cameraA presentation to show different types of camera
A presentation to show different types of cameraHollySheldon
 
Self-Injurious Behavior
Self-Injurious BehaviorSelf-Injurious Behavior
Self-Injurious Behaviorfaulkss
 
Reporte de practica. isa
Reporte de practica. isaReporte de practica. isa
Reporte de practica. isaIsabo Fierro
 
Textile Companies(EID Intern, GE Power & Water (RGM) Industrial System )
Textile Companies(EID Intern, GE Power & Water (RGM) Industrial System )Textile Companies(EID Intern, GE Power & Water (RGM) Industrial System )
Textile Companies(EID Intern, GE Power & Water (RGM) Industrial System )Mostafa Elmeshad
 

En vedette (20)

Commit Log in English
Commit Log in EnglishCommit Log in English
Commit Log in English
 
Estrategias de enseñanza
Estrategias de enseñanzaEstrategias de enseñanza
Estrategias de enseñanza
 
3er reporte
3er reporte3er reporte
3er reporte
 
La historia del curriculum
La historia del curriculumLa historia del curriculum
La historia del curriculum
 
Nozzles
NozzlesNozzles
Nozzles
 
Gebeurtenis
GebeurtenisGebeurtenis
Gebeurtenis
 
La noción del medio
La noción del medioLa noción del medio
La noción del medio
 
Portafolio digital
Portafolio digitalPortafolio digital
Portafolio digital
 
Mapas mentales
Mapas mentalesMapas mentales
Mapas mentales
 
El conflicto sobre la educación
El conflicto sobre la educaciónEl conflicto sobre la educación
El conflicto sobre la educación
 
Spring Symposium
Spring Symposium Spring Symposium
Spring Symposium
 
Toys ar alive
Toys ar aliveToys ar alive
Toys ar alive
 
La competencia como organizadora
La competencia como organizadoraLa competencia como organizadora
La competencia como organizadora
 
A presentation to show different types of camera
A presentation to show different types of cameraA presentation to show different types of camera
A presentation to show different types of camera
 
13207857 pps7
13207857 pps713207857 pps7
13207857 pps7
 
Self-Injurious Behavior
Self-Injurious BehaviorSelf-Injurious Behavior
Self-Injurious Behavior
 
Reporte de practica. isa
Reporte de practica. isaReporte de practica. isa
Reporte de practica. isa
 
Disability
DisabilityDisability
Disability
 
Textile Companies(EID Intern, GE Power & Water (RGM) Industrial System )
Textile Companies(EID Intern, GE Power & Water (RGM) Industrial System )Textile Companies(EID Intern, GE Power & Water (RGM) Industrial System )
Textile Companies(EID Intern, GE Power & Water (RGM) Industrial System )
 
Planeaciones
Planeaciones Planeaciones
Planeaciones
 

Similaire à Effective unit testing ch3. 테스트더블

Clean code
Clean codeClean code
Clean codebbongcsu
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅NAVER D2
 
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 TestOkjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 Testbeom kyun choi
 
Legacy code refactoring video rental system
Legacy code refactoring   video rental systemLegacy code refactoring   video rental system
Legacy code refactoring video rental systemJaehoon Oh
 
Sonarqube 20160509
Sonarqube 20160509Sonarqube 20160509
Sonarqube 20160509영석 조
 
10장 결과 검증
10장 결과 검증10장 결과 검증
10장 결과 검증dagri82
 
Multi-thread : producer - consumer
Multi-thread : producer - consumerMulti-thread : producer - consumer
Multi-thread : producer - consumerChang Yoon Oh
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010Ryan Park
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10Ryan Park
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)문익 장
 
테스터가 말하는 테스트코드 작성 팁과 사례
테스터가 말하는 테스트코드 작성 팁과 사례테스터가 말하는 테스트코드 작성 팁과 사례
테스터가 말하는 테스트코드 작성 팁과 사례SangIn Choung
 
The roadtocodecraft
The roadtocodecraftThe roadtocodecraft
The roadtocodecraftbbongcsu
 
테스트가 뭐예요?
테스트가 뭐예요?테스트가 뭐예요?
테스트가 뭐예요?Kyoung Up Jung
 
[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원
[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원
[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원탑크리에듀(구로디지털단지역3번출구 2분거리)
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GDG Korea
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심흥배 최
 
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It종빈 오
 

Similaire à Effective unit testing ch3. 테스트더블 (20)

Tdd 4장
Tdd 4장Tdd 4장
Tdd 4장
 
Spring Boot 2
Spring Boot 2Spring Boot 2
Spring Boot 2
 
Clean code
Clean codeClean code
Clean code
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
 
Cygnus unit test
Cygnus unit testCygnus unit test
Cygnus unit test
 
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 TestOkjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
 
Legacy code refactoring video rental system
Legacy code refactoring   video rental systemLegacy code refactoring   video rental system
Legacy code refactoring video rental system
 
Sonarqube 20160509
Sonarqube 20160509Sonarqube 20160509
Sonarqube 20160509
 
10장 결과 검증
10장 결과 검증10장 결과 검증
10장 결과 검증
 
Multi-thread : producer - consumer
Multi-thread : producer - consumerMulti-thread : producer - consumer
Multi-thread : producer - consumer
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)
 
테스터가 말하는 테스트코드 작성 팁과 사례
테스터가 말하는 테스트코드 작성 팁과 사례테스터가 말하는 테스트코드 작성 팁과 사례
테스터가 말하는 테스트코드 작성 팁과 사례
 
The roadtocodecraft
The roadtocodecraftThe roadtocodecraft
The roadtocodecraft
 
테스트가 뭐예요?
테스트가 뭐예요?테스트가 뭐예요?
테스트가 뭐예요?
 
[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원
[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원
[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심
 
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
[WELC] 22. I Need to Change a Monster Method and I Can’t Write Tests for It
 

Effective unit testing ch3. 테스트더블

  • 2. 테스트 더블 “테스트 더블”은 무엇인가? 테스트하려는 코드를 주변에서 분리하게 도와 주는 놈! 또는 테스트 작성 시 테스트 대상 코드와 상호작용하는 객체
  • 3. 테스트 대상 코드와 협력 객체를 분리 출처 : Effective Unit Testing
  • 4. 테스트 더블의 위력! ● 테스트 대상 코드를 격리한다. ● 테스트 속도를 개선한다. ● 예측 불가능한 실행 요소를 제거한다. ● 특수한 상황을 시뮬레이션한다. ● 감춰진 정보를 얻어낸다.
  • 5. 예) 테스트 대상코드(Car)와 협력 객체(Engine과 Rout) public class Car { private Engine engine; public Car(Engine engine) { this.engine = engine;} public void start() { engine.start(); } public void drive(Route route) { for(Directions directions : route.directions()){ directions.follow(); } } public void stop(){ engine.stop(); } }
  • 6. 테스트 대상 코드를 격리한다. ● Car는 Engine과 Route를 직접 사용하지만, Directions는 Route를 통해 간접적으로 만 사용 ● 즉, 협력 객체로 부터 Car를 격리하는 일은 Engine과 Route만 테스트 더블로 교체. 출처 : Effective Unit Testing 출처 : Effective Unit Testing
  • 7. 테스트 속도를 개선한다. ● 만약 Car가 이동할 최단경로를 구할 때 Route가 가중 그래프 검색 알 고리즘을 이용한다면 ? ○ 알고리즘을 계산하느라, 속도가 느려짐 ● 테스트 더블을 이용해서 사전에 계산해둔 경로를 반환 한다면? ○ 테스트는 눈부시게 빨리짐!
  • 8. 예측 불가능한 실행 요소를 제거한다. public class Route { private Clock clock = new Clock(); private ShortestPath algorithm = new …(); public Collection<Directions> directions() { if(clock.isRushHour()) { return algorithm.avoidBusyIntersections(); } return algorithm.calculateRouteBetween(...); } } 혼잡한 시간에는 경로 계산 결과가 달라진다! ● 비결정적인 요인을 다룰땐, 테스트 더블! ○ 항상 똑같은 시간을 알려주는 테스트 더블로 변경!
  • 9. 특수한 상황을 시뮬레이션한다. ● Route가 Directions를 구할 때 구글 맵스를 이용한다고 가정 해보자. ○ 목적지까지 경로를 요청하는 도중 인터넷이 끊긴 경우 Route는 잘 대처하는지 어떡해 확인 할 수 있을까? 연결 요청을 처리하는 부분을 테스트 더블로 대체해서 예외 발생시키자!
  • 10. 감춰진 정보를 얻어낸다. ● 시나리오 ○ 누군가 Car의 시동을 걸면 Car는 Engine을 가동한다. ○ 이 동작이 실제로 일어났는지 어떻게 확인 할 수 있을 까? ● 역시 테스트 더블이 해결책!
  • 11. 감춰진 정보를 얻어낸다. public class CarTest { @Test public void engineIsStartedWhenCarStarts() { TestEngine engine = new TestEngine(); new Car(engine).start(); assertTrue(engine.isRunning()); } } public class TestEngine extends Engine { private boolean isRunning; public void start(){isRunning = true;} public boolean isRunning(){return isRunning;} }
  • 12. 테스트 더블의 종류 테스트 더블 테스트 스텁 가짜 객체 테스트 스파이 Mock 객체
  • 13. 테스트 스텁 - 유난히 짧다. ● 스텁의 사전적 정의 ○ 스텁 (명사) 끝이 잘렸거나 유난히 짧은 것 ● 테스트 스텁의 목적은 원래의 구현을 최대한 단순한 것으로 대체 하는 것 스텁의 전형적인 모습! ( 아.무.것.도.하.지.않.아.요 ) public class LoggerStub implements Logger { public void log(LogLevel level, String message) { } }
  • 14. 테스트 스텁 - 유난히 짧다. public class LoggerStub implements Logger { public void log(LogLevel level, String message) { // 여전히 아무 일도 하지 않는다. } public LogLevel getLogLevel() { return LogLevel.WARN; // 하드코딩된 값을 반환한다. } } LogLevel을 반환하는 메서드 정의 스텁을 사용하는 세 가지 이유 1. 테스트는 대상 코드가 로깅하는 내용에는 전혀 관심 없다. 2. 가동 중인 로그 서버가 없으니 로깅은 어차피 실패했을 거다. 3. 테스트 스위트가 콘솔로 대량의 정보를 쏟아내는 건 바라지 않는다. (파일에 쓰는 건 별로 상관없다.)
  • 15. 가짜 객체 - 뒤끝 없이 처리한다. ● 언제 사용? ○ 최소한의 행동을 취해주거나 입력값에 따라 다르게 행동 할때 사용! ● 왜 사용? ○ 진짜 객체를 사용할때 생기는 부수효과나 연쇄동작이 일어나지 않게 경 량화 및 최적화 한 것
  • 16. 가짜 객체 - 뒤끝 없이 처리한다. public class FakeUserRepository implements UserRepository { private Collection<User> users = …. // 인메모리 데이터베이스 public void save(User user){ if( findById(user.getId()==null ) { users.add(user); } } public User findById(long id) { for( User user : users ) { if( user.getId() == id ) return user; } return null; } } public interface UserRepository { void save(User user); User findById(long id); }
  • 17. 테스트 스파이 - 기밀을 훔친다. ● 언제 사용? ○ 입력 인자로 사용되는 객체가 테스트에 필요한 정보를 알려주는 API를 제 공하지 않을 때 유용 ○ 구현 어디에도 전달된 메시지가 잘 기록되었는지 알려주는 메서드가 보이 지 않을 시 주의 : 테스트 스파이를 사용해야 하는 상황이 발생하면 설계가 제대로 되었는지 한번쯤 의심을 ;ㅁ;
  • 18. 테스트 스파이 - 기밀을 훔친다. 코드 - 테스트에 필요한 정보를 제공하지 않아 테스트 스파이가 필요한 상황 public class DLog{ private final DLogTarget[] targets; public DLog(DLogTarget… targets) { this.targets = targets; } public void write(Level level, String message) { for (DlogTarget each : targets) { each.write(level, message); } } } public interface DLogTarget { void write(Level level, String message); }
  • 19. 테스트 스파이 - 기밀을 훔친다. public class DLogTest{ @Test public void writeEachMessage…() { SpyTarget spy = new SpyTarget(); DLog log = new DLog(spy); log.write(Level.INFO, “message”); assertTrue(spy.received(Level.INFO, “message”); } private class SpyTarget implements DLogTarget { private List<String> log = ….; public void write(Level level, String message) { log.add(concatenated(level, message)); } boolean received(Level level, String message) { return log.contains(concatenated(level, message)); } private String concatenated(Level level, String message){ return level.getName() + “: “ + message; } } } 코드 - 간단히 구현해본 테스트 스파이
  • 20. Mock 객체 - 예기치 않은 일을 막아준다. ● 특정 조건이 발생하면 미리 약속된 행동을 취하고, 약속된 행동이 취해지지 않으면 바 로 테스트 실패가 된다. ○ 예 ■ UserRespository 으로 설명 하자면, findById()의 파라미터로 123을 주면 null, 124를 주면 가짜 user객체를 반환하는 식이다. ● 메서드를 파라미터에 따라 다르게 처리하게 한 스텁 수준 이지만, 이게 다가 아니다. ■ 하지만 123,124 외에 인자를 넘겼거나 다른 메서드를 호출하면 테스트를 실패하게 만들 수 있다. ● 이전 보다(스텁,가짜,스파이) 훨씬 정교한 테스트를 만들 수 있다. ○ 메서드가 호출되었는지? 몇번 호출되었는지 확인 할 수 있다.
  • 21. Mock 객체 - 예기치 않은 일을 막아준다. ● Mock 객체 라이브러리 ○ Mockito ○ JMock ○ EasyMock
  • 22. Mock 객체 - 예기치 않은 일을 막아준다. public class TestTranslator { @Test public void userInternetForTranslation() { //given final Internet internet = mock(Internet.class); given(internet.get(with(containsString(“langpair=en%7Cfi”))) .willReturn(returnValue(“{“translatedText”:”kukka”}”)); //when Translator t = new Translator(internet); String translation = t.translate(“flower”, ENGLISH, FINNISH); //then assertEquals(“kukka”, translation); } }
  • 23. 테스트 더블 활용 지침 ● 용도에 맞는 도구를 꺼내 써라 ● 준비하고, 시작하고, 단언하라 ● 구현이 아니라 동작을 확인하라 ● 자신의 도구를 선택해라 ● 종속 객체를 주입하라
  • 24. 용도에 맞는 더블을 선택해라. ● “가독성” - 테스트를 가장 읽기 쉽게 만들어주는 선택 ● 그 외 ○ 두 객체 간 상호작용의 결과로 특정메서드가 호출되었는지 확인하고 싶다면 Mock 객체 ○ …... ○ 이도 저도 아니라면 동전을 던져보자, 앞면 Mock, 뒷면 스텁
  • 25. 용도에 맞는 더블을 선택해라. ● 결론 ○ 스텁은 질문하고 Mock은 행동한다.
  • 26. 구현이 아니라 동작을 확인하라. ● 검증 목적과 관련 없는 지극히 사소한 변경마저도 테스트 실패 한다면.. ○ 못질을 너무 많이 해서 구멍이 송송 뚫린 불쌍한 목판처럼 되어 버린다. ● 테스트는 오직 한 가지만 검사해야 하고 그 의도를 명확히 전달하도록 작성되어야 한 다. ● 핵심 ○ “구현이 아니라 동작을 검증 하자!”
  • 27. 종속 객체를 주입하라 ● 진짜 객체를 테스트 더블 객체로 교체할 수 있어야 한다. 교체할 수 없다면 단위 테스트 작성도 못한다. ○ 종속 객체를 private 필드에 저장하거나 팩토리 메서드 등을 통 해 외부로부터 얻도록 해야 함 ○ 보통 생성자 주입 방식을 많이 애용 함