SlideShare ist ein Scribd-Unternehmen logo
1 von 30
Mock을 이용한 TDD 테스트 주도개발 실천법과 도구 2011.02.26 원종필
Ex) 사용자 암호 저장기능에 대한 테스트 케이스 public void testSavePassword() throw Exception { UserRegister register = new UserRegister(); Cipher cipher = ???	// TODO 암호화 필요 String userId = "sweet88”; String password = "potato"; register.savePassword(userId, cipher.encrypt(password)); String decryptedPassword = cipher.decrypt(register.getPassword(userId)); assertEquals(password, decryptedPassword) } ? Cipher에서 MD5 암호화/복호화 처리를 해야 하는데… 아직 UserRegister구현도 안했는데.. TDD를 하려면 Cipher도 구현하면서 해야하는가??
그래! 이거야!! MD5를 적용하고 있는 것 처럼  보이는 객체를 만들어서 개발하자!
MD5 동작을 흉내내어서.. public class MockMD5Cipher implements Cipher { public String decrypt(String source) { return "potato” } public String encrypt(String source) { return "8ee2027983915ec78acc45027d874316" 	} } public void testSavePassword() throw Exception { UserRegister register = new UserRegister(); Cipher cipher = new MockMD5Cipher(); String userId = "sweet88"; String password = "potato"; register.savePassword(userId, cipher.encrypt(password)); String decryptedPassword = cipher.decrypt(register.getPassword(userId)); assertEquals(password, decryptedPassword) } Cipher 구현에 관계없이 UserRegister테스트를 잘 진행할 수 있다~
Mock Object MockMD5Cipher와 같이 실제 모듈과  비슷하게 보이도록 만든 각자 객체
MockObject 조작하기 쉬운 재료를 이용해 추후 만들어질  제품의 외향을 흉내 낸 모조품 모듈의 겉모양이 실제 모듈과  비슷하게 보이도록 만든 가짜 객체 실제 객체를 만들기엔 비용과 시간이  많이 들거나 의존성이 길게 걸쳐져 있어  제대로 구현하기 어려운 경우 사용
MockObject를 사용하는 예 테스트 작성을 위한 환경 구축이 어려워서 Ex) 환경구축에 시간이 많이 소요되는 상황 사용해야하는 모듈이 개발전 타부서와 협의,정책이 필요한 경우 테스트가 특정 상황이나 순간에 의존적이라서 Ex) FTP클라이언트에서 접속시도후 5초까지 1초마다 접속 재시도하고 그 이후엔 연결 실패 메시지를 띄우는 기능 테스트와 같은경우 테스트 시간이 오래 걸려서 Ex) 네트워크를 이용해서 시간이 걸리는 경우에 영향 테스트
Test Double 실제 객체를 사용해서 테스트를 진행하기  어려울 경우 이를 대신해서 테스트를  진행할 수 있도록 만들어지는 객체를 지칭
Test Double을  하나씩 살펴봅시다
Dummy Object 인스턴스화된 객체가 필요할 뿐  해당 객체의 기능까지는 필요하지  않는 경우에 사용 public class DummyCouponimplements ICoupon { public intgetDiscountPercent() {return 0;} public String getName() {return null;} public booleanisAppliable(Item item) {return false;} public booleanisValid() {return false;} public void doExpire() {} } 더미 객체의 메소드는호출을  가정하고 만들어진게 아니다 메소드의 리턴값은 기본값을 반환 또는 메소드 호출시 에러를 발생시키기도 한다
Dummy Object사용 예제 public class DummyCouponimplements ICoupon { public intgetDiscountPercent() {return 0;} public String getName() {return null;} public booleanisAppliable(Item item) {return false;} public booleanisValid() {return false;} public void doExpire() {} } public void testAddCoupon() throws Exception { User user = new User("area88"); assertEquals("쿠폰 수령", 0, user.getTotalCouponCount()); ICouponcoupon = new DummyCoupon(); user.addCoupon(coupon); assertEquals("쿠폰 수령 후", 1, user.getTotalCouponCount()); }
Test Stub 더미 객체가 마치 실제로 동작하는 것처럼  보이게 만들어 놓은 객체 public class StubCouponimplements ICoupon { public intgetDiscountPercent() { return 7; } public String getName() { return "VIP 고객 한가위 감사쿠폰"; } public booleanisAppliable(Item item) { return true; } public booleanisValid() { return true; } public void doExpire() {} } public void testGetLastOccupiedCoupon() throw Exception { User user = new User("area88"); ICouponeventCoupon = new StubCoupon(); user.addCoupon(eventCoupon); ICouponlastCoupon = user.getLastOccupiedCoupon(); assertEquals("쿠폰 할인율", 7, lastCoupon.getDiscountPercent()); assertEquals("쿠폰 이름", "VIP 고객 한가위 감사쿠폰", lastCoupon.getName()); }
Dummy Vs Stub Dummy 단지 인스턴스화 될 수 있는 객체 수준 Stub 인스턴스화된 객체가  특정 상태나 모습을 대표
Stub의 단점 Stub은 특정 객체의  상태가 하드 코딩된 형태 로직이 들어가는 부분의  테스트를 할 수 없다
Fake Object 여러 개의 인스턴스를 대표할 수 있는 경우이거나 좀더 복잡한 구현이 들어가 있는 객체 복잡한 로직, 객체 내부에서 필요로 하는 다른  외부 객체들의 동작을비교적 단순하게 구현한 객체 테스트 케이스 작성을 진행하기 위해 필요한  다른 객체들과의 의존성을 제거하기 위해 사용
public class FakeCouponimplements ICoupon { List<String> categoryList = new ArrayList(); public FakeCoupon() { categoryList.add("큰칼"); categoryList.add("아주큰칼"); categoryList.add("짧은"); } public booleanisAppliable(Item item) { if(this.categoryList.contains(item.getCategory())) { return true; } return false; } // …} public class PriceCalculator { public intgetOrderPrice(Item item, ICoupon coupon) { if(coupon.isValid() && coupon.isAppliable(item)) { //discount} 	} } public void testGetOderPrice() throws Exception() { PriceCalculator calculator = new PriceCalculator(); Item discount_item = new Item("LightSavor", "큰칼", 10000); ICoupon coupon = new FakeCoupon(); asserEquals("할인된 가격", 9300, calculator.getOrderPrice(item,coupon)); Item not_discount_item = new Item("Sasimi", "사시미", 10); assertEquals("할인안된 가격", 10, calculator.getOrderPrice(item, coupon)); }
Fake Object 사용 주의 Fake Object를 만들때 지나치게 집중하면 페이크 객체  자체를 테스트 해야할 정도로 복잡해질 수 있다  적절한 수준에서 구현을 접고 Mockframework 또는  실제 객체를 사용하여 테스트 케이스 작성을 권장
Test Spy 특정 객체가 사용됐는지, 특정 메소드가  호출되었는지 확인 필요할 때 사용  호출 여부를 감시하여 기록해 두었다가  요청이 들어오면 해당 기록 정보를 전달한다 public class SpyCouponimplements ICoupon { List<String> categoryListnew ArrayList(); private intappliableCallCount; public booleanisAppliable(Item item) { appliableCallCount++; if(this.categoryList.contains(item.getCategory())) { return true; 		} return false; } public intgetAppliableCallCount() { return this.appliableCallCount; } }
Test Spy 사용 주의  아주 특수한 경우를 제외하고 잘 쓰이지 않는다 테스트 스파이가 필요한 경우 Mock Framework 이용이 더 편함 대부분의 Mock Framework에서  기본적으로 Test Spy기능을 제공
상태기반 테스트 Vs 행위기반 테스트 상태 기반 테스트(State Base Test) 테스트 대상 클래스의 메소드를 호출하고  그결과 값과 예상값을 비교하는 방식 행위 기반 테스트(Behavior Base Test) 올바른 로직 수행에 판단의 근거로  특정한 동작의 수행여부를 사용 메소드의 리턴값이 없거나 리턴값 확인만으로  예상대로 동작했음을 보증하기 어려움
행위 기반 테스트가 필요한 예 MethodB MethodA 입력A call MethodB MethodA 입력B MethodA를 테스트 하는 경우 입력값에  따른 차이를 MethodA 리턴값 조사만으로 알수 없다 MethodB의 호출여부를 조사하지 않으면  MethodA 정상 동작 여부를 판단할 수 없다 Test Spy를 사용하거나 자체적으로  검증 기능이 있는 Mock 객체를 사용
Mock Object 행위를 검증하기 위해 사용되는 객체를 지칭  수동으로 만드는건 고통이  매우 크기 때문에 대부분 MockFramework를 이용
Mock Framework 테스트 예 일반적인 테스트 ICoupon coupon = new FakeCoupon(); user.addCoupon(coupon); assertEquals(1, user.getTotalCouponCount()); addCoupon() 내부에서 뭔가가  잘되고 있는지 테스트하기 힘들다  Mock Framework을 이용한 테스트 ICoupon coupon = mock(ICoupon.class); coupon.expects(once().method("isValid") 		.withAnyArguments() 		.will(returnValue(true)); user.addCoupon(coupon); assertEquals(1, user.getTotalCouponCount()); isValid 메소드가 1번  호출될 것을 예상 isValid에서 사용할 인자는  무엇이든 상관안함  호출시 리턴값은 true를  돌려주게 될 것임
Mock Object 용어에 대한 고찰 기존에 설명했던 부분에서는.. MockObject ==  ‘행위 기반 테스트를 위해 사용하는 객체’ 앞으로는.. Mock Object == Test Double과  동일한 의미로 사용할 예정 Mocking은 행위 기반 테스트 객체가 아니라  Test Double객체를 만드는것을 의미
Mock Framework또는 모의 객체 프레임워크 Mock Framework 사용시 좋은점 Mock 객체를 직접 작성해서  명시적인 클래스를 만들지 않아도 된다 Mock 객체에 대해 행위까지도 테스트 케이스에 포함시킬 수 있다 대표적인Mock Framework EasyMock jMock Mockito
대표적인 Mock Framework의 사용법 각자 알아서.. 책을 읽으면서    실습으로 배워보세요 스스로 학습… 사용법은 비슷비슷합니다
Mock Framework 사용시 유의사항 Mock 프레임워크가 정말 필요한지 잘 따져본다 Mock 프레임워크를 사용하는 테 스트케이스의 유지 비용이 지속적으로 발생 가능하다면 설계를 바꿔서라도  Mock 필요없는 의존성 적은 구조로 만드는게 더 좋다 투자 대비 수익이 확실할 때만 사용 Mock을 사용할때는 좀더 길게 볼 필요가 있다 테스트 편의를 위해 사용하기 시작한 Mock객체들이  개발진척의 발목을 잡을수도있다
Mock Framework 사용시 유의사항 어떤 Mock 프레임워크를 사용하느냐는  핵심적인 문제가 아니다 유행따라 최고의 Mock 프레임워크를 찾아  떠나는 행동은 하지마라 대부분의 경우  간단한 Mock 객체만으로도 충분하다 Mock은 Mock일 뿐 Mock을 사용한 테스트에서 잘동작해서  실제 객체를 적용해서 잘되리라는 보장은 없다 초반부터 실제객체를 사용 가능하다면  Mock객체를 사용하지 말고 실제객체를 사용해라
Q / A
END

Weitere ähnliche Inhalte

Was ist angesagt?

[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로Oracle Korea
 
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기NAVER Engineering
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GDG Korea
 
KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기Ryan Park
 
[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종빈 오
 
프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js function프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js functionYoung-Beom Rhee
 
GKAC 2015 Apr. - Android Looper
GKAC 2015 Apr. - Android LooperGKAC 2015 Apr. - Android Looper
GKAC 2015 Apr. - Android LooperGDG Korea
 
프론트엔드스터디 E03 - Javascript intro.
프론트엔드스터디 E03 - Javascript intro.프론트엔드스터디 E03 - Javascript intro.
프론트엔드스터디 E03 - Javascript intro.Young-Beom Rhee
 
Jquery javascript_ed10
Jquery javascript_ed10Jquery javascript_ed10
Jquery javascript_ed10hungrok
 
파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229Yong Joon Moon
 
파이썬+Operator+이해하기 20160409
파이썬+Operator+이해하기 20160409파이썬+Operator+이해하기 20160409
파이썬+Operator+이해하기 20160409Yong Joon Moon
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)beom kyun choi
 
시작하자 단위테스트
시작하자 단위테스트시작하자 단위테스트
시작하자 단위테스트YongEun Choi
 
구글테스트
구글테스트구글테스트
구글테스트진화 손
 
Java script 강의자료_ed13
Java script 강의자료_ed13Java script 강의자료_ed13
Java script 강의자료_ed13hungrok
 
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...Young-Beom Rhee
 
120908 레거시코드활용전략 4장5장
120908 레거시코드활용전략 4장5장120908 레거시코드활용전략 4장5장
120908 레거시코드활용전략 4장5장tedypicker
 
헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리은숙 이
 
포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++KWANGIL KIM
 

Was ist angesagt? (20)

[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
 
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
 
KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기
 
[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
 
프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js function프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js function
 
GKAC 2015 Apr. - Android Looper
GKAC 2015 Apr. - Android LooperGKAC 2015 Apr. - Android Looper
GKAC 2015 Apr. - Android Looper
 
프론트엔드스터디 E03 - Javascript intro.
프론트엔드스터디 E03 - Javascript intro.프론트엔드스터디 E03 - Javascript intro.
프론트엔드스터디 E03 - Javascript intro.
 
Jquery javascript_ed10
Jquery javascript_ed10Jquery javascript_ed10
Jquery javascript_ed10
 
파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229
 
파이썬+Operator+이해하기 20160409
파이썬+Operator+이해하기 20160409파이썬+Operator+이해하기 20160409
파이썬+Operator+이해하기 20160409
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)
 
시작하자 단위테스트
시작하자 단위테스트시작하자 단위테스트
시작하자 단위테스트
 
구글테스트
구글테스트구글테스트
구글테스트
 
Java script 강의자료_ed13
Java script 강의자료_ed13Java script 강의자료_ed13
Java script 강의자료_ed13
 
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
 
Redux
ReduxRedux
Redux
 
120908 레거시코드활용전략 4장5장
120908 레거시코드활용전략 4장5장120908 레거시코드활용전략 4장5장
120908 레거시코드활용전략 4장5장
 
헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리
 
포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++
 

Andere mochten auch

파이썬3프로그래밍 2장 2003
파이썬3프로그래밍 2장 2003파이썬3프로그래밍 2장 2003
파이썬3프로그래밍 2장 2003Jong Pil Won
 
TDD&Refactoring Day 02: TDD
TDD&Refactoring Day 02: TDDTDD&Refactoring Day 02: TDD
TDD&Refactoring Day 02: TDDSuwon Chae
 
Tdd 실습&나머지
Tdd 실습&나머지Tdd 실습&나머지
Tdd 실습&나머지Jong Pil Won
 
[2012 01 28]cleancode 3장
[2012 01 28]cleancode 3장[2012 01 28]cleancode 3장
[2012 01 28]cleancode 3장Jong Pil Won
 
[2016-03-09] TDD on Spring ~ 봄에는 TDD ~
[2016-03-09] TDD on Spring ~ 봄에는 TDD ~[2016-03-09] TDD on Spring ~ 봄에는 TDD ~
[2016-03-09] TDD on Spring ~ 봄에는 TDD ~Ashal aka JOKER
 
Tdd retro agile_korea_게시용
Tdd retro agile_korea_게시용Tdd retro agile_korea_게시용
Tdd retro agile_korea_게시용Sangcheol Hwang
 
TDD: Test Driven Development 첫번째 이야기
TDD: Test Driven Development 첫번째 이야기TDD: Test Driven Development 첫번째 이야기
TDD: Test Driven Development 첫번째 이야기Ji Heon Kim
 
행복한 개발을 위한_테스트_케이스
행복한 개발을 위한_테스트_케이스행복한 개발을 위한_테스트_케이스
행복한 개발을 위한_테스트_케이스도형 임
 
테스트 케이스와 SW 품질
테스트 케이스와 SW 품질테스트 케이스와 SW 품질
테스트 케이스와 SW 품질도형 임
 
Tdd 왜 배우기 어려운가
Tdd 왜 배우기 어려운가Tdd 왜 배우기 어려운가
Tdd 왜 배우기 어려운가Jaehoon Oh
 
테스트 자동화와 TDD(테스트 주도 개발방법론)
테스트 자동화와 TDD(테스트 주도 개발방법론)테스트 자동화와 TDD(테스트 주도 개발방법론)
테스트 자동화와 TDD(테스트 주도 개발방법론)KH Park (박경훈)
 

Andere mochten auch (11)

파이썬3프로그래밍 2장 2003
파이썬3프로그래밍 2장 2003파이썬3프로그래밍 2장 2003
파이썬3프로그래밍 2장 2003
 
TDD&Refactoring Day 02: TDD
TDD&Refactoring Day 02: TDDTDD&Refactoring Day 02: TDD
TDD&Refactoring Day 02: TDD
 
Tdd 실습&나머지
Tdd 실습&나머지Tdd 실습&나머지
Tdd 실습&나머지
 
[2012 01 28]cleancode 3장
[2012 01 28]cleancode 3장[2012 01 28]cleancode 3장
[2012 01 28]cleancode 3장
 
[2016-03-09] TDD on Spring ~ 봄에는 TDD ~
[2016-03-09] TDD on Spring ~ 봄에는 TDD ~[2016-03-09] TDD on Spring ~ 봄에는 TDD ~
[2016-03-09] TDD on Spring ~ 봄에는 TDD ~
 
Tdd retro agile_korea_게시용
Tdd retro agile_korea_게시용Tdd retro agile_korea_게시용
Tdd retro agile_korea_게시용
 
TDD: Test Driven Development 첫번째 이야기
TDD: Test Driven Development 첫번째 이야기TDD: Test Driven Development 첫번째 이야기
TDD: Test Driven Development 첫번째 이야기
 
행복한 개발을 위한_테스트_케이스
행복한 개발을 위한_테스트_케이스행복한 개발을 위한_테스트_케이스
행복한 개발을 위한_테스트_케이스
 
테스트 케이스와 SW 품질
테스트 케이스와 SW 품질테스트 케이스와 SW 품질
테스트 케이스와 SW 품질
 
Tdd 왜 배우기 어려운가
Tdd 왜 배우기 어려운가Tdd 왜 배우기 어려운가
Tdd 왜 배우기 어려운가
 
테스트 자동화와 TDD(테스트 주도 개발방법론)
테스트 자동화와 TDD(테스트 주도 개발방법론)테스트 자동화와 TDD(테스트 주도 개발방법론)
테스트 자동화와 TDD(테스트 주도 개발방법론)
 

Ähnlich wie Tdd 4장

Effective unit testing ch3. 테스트더블
Effective unit testing   ch3. 테스트더블Effective unit testing   ch3. 테스트더블
Effective unit testing ch3. 테스트더블YongEun Choi
 
Refactoring - Chapter 8.2
Refactoring - Chapter 8.2Refactoring - Chapter 8.2
Refactoring - Chapter 8.2Ji Ung Lee
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅NAVER D2
 
Naver api for android
Naver api for androidNaver api for android
Naver api for androidSangon Lee
 
08장 객체와 클래스 (기본)
08장 객체와 클래스 (기본)08장 객체와 클래스 (기본)
08장 객체와 클래스 (기본)유석 남
 
[ES6] 10. Generator
[ES6] 10. Generator[ES6] 10. Generator
[ES6] 10. GeneratorHan JaeYeab
 
Javascript 교육자료 pdf
Javascript 교육자료 pdfJavascript 교육자료 pdf
Javascript 교육자료 pdfHyosang Hong
 
Why use Dagger in Android
Why use Dagger in AndroidWhy use Dagger in Android
Why use Dagger in Androidkiyoung lee
 
[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분거리)
 
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍Young-Beom Rhee
 
Design patterns
Design patternsDesign patterns
Design patternsdf
 
C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기Heo Seungwook
 
Boost라이브러리의내부구조 20151111 서진택
Boost라이브러리의내부구조 20151111 서진택Boost라이브러리의내부구조 20151111 서진택
Boost라이브러리의내부구조 20151111 서진택JinTaek Seo
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)문익 장
 
Python 테스트 시작하기
Python 테스트 시작하기Python 테스트 시작하기
Python 테스트 시작하기Hosung Lee
 
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기Kenneth Ceyer
 
Android UI Test (Espresso/Kakao)
Android UI Test (Espresso/Kakao)Android UI Test (Espresso/Kakao)
Android UI Test (Espresso/Kakao)MDLicht
 

Ähnlich wie Tdd 4장 (20)

Effective unit testing ch3. 테스트더블
Effective unit testing   ch3. 테스트더블Effective unit testing   ch3. 테스트더블
Effective unit testing ch3. 테스트더블
 
Refactoring - Chapter 8.2
Refactoring - Chapter 8.2Refactoring - Chapter 8.2
Refactoring - Chapter 8.2
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
 
Naver api for android
Naver api for androidNaver api for android
Naver api for android
 
Spring Boot 2
Spring Boot 2Spring Boot 2
Spring Boot 2
 
W14 chap13
W14 chap13W14 chap13
W14 chap13
 
08장 객체와 클래스 (기본)
08장 객체와 클래스 (기본)08장 객체와 클래스 (기본)
08장 객체와 클래스 (기본)
 
[ES6] 10. Generator
[ES6] 10. Generator[ES6] 10. Generator
[ES6] 10. Generator
 
Javascript 교육자료 pdf
Javascript 교육자료 pdfJavascript 교육자료 pdf
Javascript 교육자료 pdf
 
Why use Dagger in Android
Why use Dagger in AndroidWhy use Dagger in Android
Why use Dagger in Android
 
[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전문교육학원
 
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍
 
Design patterns
Design patternsDesign patterns
Design patterns
 
C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기
 
Boost라이브러리의내부구조 20151111 서진택
Boost라이브러리의내부구조 20151111 서진택Boost라이브러리의내부구조 20151111 서진택
Boost라이브러리의내부구조 20151111 서진택
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)
 
Swt J Face 2/3
Swt J Face 2/3Swt J Face 2/3
Swt J Face 2/3
 
Python 테스트 시작하기
Python 테스트 시작하기Python 테스트 시작하기
Python 테스트 시작하기
 
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 
Android UI Test (Espresso/Kakao)
Android UI Test (Espresso/Kakao)Android UI Test (Espresso/Kakao)
Android UI Test (Espresso/Kakao)
 

Mehr von Jong Pil Won

[2012 11 12]애자일 회고
[2012 11 12]애자일 회고[2012 11 12]애자일 회고
[2012 11 12]애자일 회고Jong Pil Won
 
[2012 03 17]clean_code 14장 점진적개선
[2012 03 17]clean_code 14장 점진적개선[2012 03 17]clean_code 14장 점진적개선
[2012 03 17]clean_code 14장 점진적개선Jong Pil Won
 
[2012 02 03]clean_code 5장
[2012 02 03]clean_code 5장[2012 02 03]clean_code 5장
[2012 02 03]clean_code 5장Jong Pil Won
 
[2012 02 03]clean_code 4장
[2012 02 03]clean_code 4장[2012 02 03]clean_code 4장
[2012 02 03]clean_code 4장Jong Pil Won
 
[2012 01 28]cleancode 1장
[2012 01 28]cleancode 1장[2012 01 28]cleancode 1장
[2012 01 28]cleancode 1장Jong Pil Won
 
[2011 05 21] 4장 제어
[2011 05 21] 4장 제어[2011 05 21] 4장 제어
[2011 05 21] 4장 제어Jong Pil Won
 
[2011 05 21] 4장 제어
[2011 05 21] 4장 제어[2011 05 21] 4장 제어
[2011 05 21] 4장 제어Jong Pil Won
 
[2011 05 21] 4장 제어
[2011 05 21] 4장 제어[2011 05 21] 4장 제어
[2011 05 21] 4장 제어Jong Pil Won
 
[2011 04 30]python-3장
[2011 04 30]python-3장[2011 04 30]python-3장
[2011 04 30]python-3장Jong Pil Won
 
10장 동기부여와훈련 경험
10장 동기부여와훈련 경험10장 동기부여와훈련 경험
10장 동기부여와훈련 경험Jong Pil Won
 

Mehr von Jong Pil Won (11)

[2012 11 12]애자일 회고
[2012 11 12]애자일 회고[2012 11 12]애자일 회고
[2012 11 12]애자일 회고
 
[2012 03 17]clean_code 14장 점진적개선
[2012 03 17]clean_code 14장 점진적개선[2012 03 17]clean_code 14장 점진적개선
[2012 03 17]clean_code 14장 점진적개선
 
[2012 02 03]clean_code 5장
[2012 02 03]clean_code 5장[2012 02 03]clean_code 5장
[2012 02 03]clean_code 5장
 
[2012 02 03]clean_code 4장
[2012 02 03]clean_code 4장[2012 02 03]clean_code 4장
[2012 02 03]clean_code 4장
 
[2012 01 28]cleancode 1장
[2012 01 28]cleancode 1장[2012 01 28]cleancode 1장
[2012 01 28]cleancode 1장
 
[2011 05 21] 4장 제어
[2011 05 21] 4장 제어[2011 05 21] 4장 제어
[2011 05 21] 4장 제어
 
[2011 05 21] 4장 제어
[2011 05 21] 4장 제어[2011 05 21] 4장 제어
[2011 05 21] 4장 제어
 
[2011 05 21] 4장 제어
[2011 05 21] 4장 제어[2011 05 21] 4장 제어
[2011 05 21] 4장 제어
 
[2011 04 30]python-3장
[2011 04 30]python-3장[2011 04 30]python-3장
[2011 04 30]python-3장
 
Tdd 마무리
Tdd 마무리Tdd 마무리
Tdd 마무리
 
10장 동기부여와훈련 경험
10장 동기부여와훈련 경험10장 동기부여와훈련 경험
10장 동기부여와훈련 경험
 

Tdd 4장

  • 1. Mock을 이용한 TDD 테스트 주도개발 실천법과 도구 2011.02.26 원종필
  • 2. Ex) 사용자 암호 저장기능에 대한 테스트 케이스 public void testSavePassword() throw Exception { UserRegister register = new UserRegister(); Cipher cipher = ??? // TODO 암호화 필요 String userId = "sweet88”; String password = "potato"; register.savePassword(userId, cipher.encrypt(password)); String decryptedPassword = cipher.decrypt(register.getPassword(userId)); assertEquals(password, decryptedPassword) } ? Cipher에서 MD5 암호화/복호화 처리를 해야 하는데… 아직 UserRegister구현도 안했는데.. TDD를 하려면 Cipher도 구현하면서 해야하는가??
  • 3. 그래! 이거야!! MD5를 적용하고 있는 것 처럼 보이는 객체를 만들어서 개발하자!
  • 4. MD5 동작을 흉내내어서.. public class MockMD5Cipher implements Cipher { public String decrypt(String source) { return "potato” } public String encrypt(String source) { return "8ee2027983915ec78acc45027d874316" } } public void testSavePassword() throw Exception { UserRegister register = new UserRegister(); Cipher cipher = new MockMD5Cipher(); String userId = "sweet88"; String password = "potato"; register.savePassword(userId, cipher.encrypt(password)); String decryptedPassword = cipher.decrypt(register.getPassword(userId)); assertEquals(password, decryptedPassword) } Cipher 구현에 관계없이 UserRegister테스트를 잘 진행할 수 있다~
  • 5. Mock Object MockMD5Cipher와 같이 실제 모듈과 비슷하게 보이도록 만든 각자 객체
  • 6. MockObject 조작하기 쉬운 재료를 이용해 추후 만들어질 제품의 외향을 흉내 낸 모조품 모듈의 겉모양이 실제 모듈과 비슷하게 보이도록 만든 가짜 객체 실제 객체를 만들기엔 비용과 시간이 많이 들거나 의존성이 길게 걸쳐져 있어 제대로 구현하기 어려운 경우 사용
  • 7. MockObject를 사용하는 예 테스트 작성을 위한 환경 구축이 어려워서 Ex) 환경구축에 시간이 많이 소요되는 상황 사용해야하는 모듈이 개발전 타부서와 협의,정책이 필요한 경우 테스트가 특정 상황이나 순간에 의존적이라서 Ex) FTP클라이언트에서 접속시도후 5초까지 1초마다 접속 재시도하고 그 이후엔 연결 실패 메시지를 띄우는 기능 테스트와 같은경우 테스트 시간이 오래 걸려서 Ex) 네트워크를 이용해서 시간이 걸리는 경우에 영향 테스트
  • 8. Test Double 실제 객체를 사용해서 테스트를 진행하기 어려울 경우 이를 대신해서 테스트를 진행할 수 있도록 만들어지는 객체를 지칭
  • 9. Test Double을 하나씩 살펴봅시다
  • 10. Dummy Object 인스턴스화된 객체가 필요할 뿐 해당 객체의 기능까지는 필요하지 않는 경우에 사용 public class DummyCouponimplements ICoupon { public intgetDiscountPercent() {return 0;} public String getName() {return null;} public booleanisAppliable(Item item) {return false;} public booleanisValid() {return false;} public void doExpire() {} } 더미 객체의 메소드는호출을 가정하고 만들어진게 아니다 메소드의 리턴값은 기본값을 반환 또는 메소드 호출시 에러를 발생시키기도 한다
  • 11. Dummy Object사용 예제 public class DummyCouponimplements ICoupon { public intgetDiscountPercent() {return 0;} public String getName() {return null;} public booleanisAppliable(Item item) {return false;} public booleanisValid() {return false;} public void doExpire() {} } public void testAddCoupon() throws Exception { User user = new User("area88"); assertEquals("쿠폰 수령", 0, user.getTotalCouponCount()); ICouponcoupon = new DummyCoupon(); user.addCoupon(coupon); assertEquals("쿠폰 수령 후", 1, user.getTotalCouponCount()); }
  • 12. Test Stub 더미 객체가 마치 실제로 동작하는 것처럼 보이게 만들어 놓은 객체 public class StubCouponimplements ICoupon { public intgetDiscountPercent() { return 7; } public String getName() { return "VIP 고객 한가위 감사쿠폰"; } public booleanisAppliable(Item item) { return true; } public booleanisValid() { return true; } public void doExpire() {} } public void testGetLastOccupiedCoupon() throw Exception { User user = new User("area88"); ICouponeventCoupon = new StubCoupon(); user.addCoupon(eventCoupon); ICouponlastCoupon = user.getLastOccupiedCoupon(); assertEquals("쿠폰 할인율", 7, lastCoupon.getDiscountPercent()); assertEquals("쿠폰 이름", "VIP 고객 한가위 감사쿠폰", lastCoupon.getName()); }
  • 13. Dummy Vs Stub Dummy 단지 인스턴스화 될 수 있는 객체 수준 Stub 인스턴스화된 객체가 특정 상태나 모습을 대표
  • 14. Stub의 단점 Stub은 특정 객체의 상태가 하드 코딩된 형태 로직이 들어가는 부분의 테스트를 할 수 없다
  • 15. Fake Object 여러 개의 인스턴스를 대표할 수 있는 경우이거나 좀더 복잡한 구현이 들어가 있는 객체 복잡한 로직, 객체 내부에서 필요로 하는 다른 외부 객체들의 동작을비교적 단순하게 구현한 객체 테스트 케이스 작성을 진행하기 위해 필요한 다른 객체들과의 의존성을 제거하기 위해 사용
  • 16. public class FakeCouponimplements ICoupon { List<String> categoryList = new ArrayList(); public FakeCoupon() { categoryList.add("큰칼"); categoryList.add("아주큰칼"); categoryList.add("짧은"); } public booleanisAppliable(Item item) { if(this.categoryList.contains(item.getCategory())) { return true; } return false; } // …} public class PriceCalculator { public intgetOrderPrice(Item item, ICoupon coupon) { if(coupon.isValid() && coupon.isAppliable(item)) { //discount} } } public void testGetOderPrice() throws Exception() { PriceCalculator calculator = new PriceCalculator(); Item discount_item = new Item("LightSavor", "큰칼", 10000); ICoupon coupon = new FakeCoupon(); asserEquals("할인된 가격", 9300, calculator.getOrderPrice(item,coupon)); Item not_discount_item = new Item("Sasimi", "사시미", 10); assertEquals("할인안된 가격", 10, calculator.getOrderPrice(item, coupon)); }
  • 17. Fake Object 사용 주의 Fake Object를 만들때 지나치게 집중하면 페이크 객체 자체를 테스트 해야할 정도로 복잡해질 수 있다 적절한 수준에서 구현을 접고 Mockframework 또는 실제 객체를 사용하여 테스트 케이스 작성을 권장
  • 18. Test Spy 특정 객체가 사용됐는지, 특정 메소드가 호출되었는지 확인 필요할 때 사용 호출 여부를 감시하여 기록해 두었다가 요청이 들어오면 해당 기록 정보를 전달한다 public class SpyCouponimplements ICoupon { List<String> categoryListnew ArrayList(); private intappliableCallCount; public booleanisAppliable(Item item) { appliableCallCount++; if(this.categoryList.contains(item.getCategory())) { return true; } return false; } public intgetAppliableCallCount() { return this.appliableCallCount; } }
  • 19. Test Spy 사용 주의 아주 특수한 경우를 제외하고 잘 쓰이지 않는다 테스트 스파이가 필요한 경우 Mock Framework 이용이 더 편함 대부분의 Mock Framework에서 기본적으로 Test Spy기능을 제공
  • 20. 상태기반 테스트 Vs 행위기반 테스트 상태 기반 테스트(State Base Test) 테스트 대상 클래스의 메소드를 호출하고 그결과 값과 예상값을 비교하는 방식 행위 기반 테스트(Behavior Base Test) 올바른 로직 수행에 판단의 근거로 특정한 동작의 수행여부를 사용 메소드의 리턴값이 없거나 리턴값 확인만으로 예상대로 동작했음을 보증하기 어려움
  • 21. 행위 기반 테스트가 필요한 예 MethodB MethodA 입력A call MethodB MethodA 입력B MethodA를 테스트 하는 경우 입력값에 따른 차이를 MethodA 리턴값 조사만으로 알수 없다 MethodB의 호출여부를 조사하지 않으면 MethodA 정상 동작 여부를 판단할 수 없다 Test Spy를 사용하거나 자체적으로 검증 기능이 있는 Mock 객체를 사용
  • 22. Mock Object 행위를 검증하기 위해 사용되는 객체를 지칭 수동으로 만드는건 고통이 매우 크기 때문에 대부분 MockFramework를 이용
  • 23. Mock Framework 테스트 예 일반적인 테스트 ICoupon coupon = new FakeCoupon(); user.addCoupon(coupon); assertEquals(1, user.getTotalCouponCount()); addCoupon() 내부에서 뭔가가 잘되고 있는지 테스트하기 힘들다 Mock Framework을 이용한 테스트 ICoupon coupon = mock(ICoupon.class); coupon.expects(once().method("isValid") .withAnyArguments() .will(returnValue(true)); user.addCoupon(coupon); assertEquals(1, user.getTotalCouponCount()); isValid 메소드가 1번 호출될 것을 예상 isValid에서 사용할 인자는 무엇이든 상관안함 호출시 리턴값은 true를 돌려주게 될 것임
  • 24. Mock Object 용어에 대한 고찰 기존에 설명했던 부분에서는.. MockObject == ‘행위 기반 테스트를 위해 사용하는 객체’ 앞으로는.. Mock Object == Test Double과 동일한 의미로 사용할 예정 Mocking은 행위 기반 테스트 객체가 아니라 Test Double객체를 만드는것을 의미
  • 25. Mock Framework또는 모의 객체 프레임워크 Mock Framework 사용시 좋은점 Mock 객체를 직접 작성해서 명시적인 클래스를 만들지 않아도 된다 Mock 객체에 대해 행위까지도 테스트 케이스에 포함시킬 수 있다 대표적인Mock Framework EasyMock jMock Mockito
  • 26. 대표적인 Mock Framework의 사용법 각자 알아서.. 책을 읽으면서 실습으로 배워보세요 스스로 학습… 사용법은 비슷비슷합니다
  • 27. Mock Framework 사용시 유의사항 Mock 프레임워크가 정말 필요한지 잘 따져본다 Mock 프레임워크를 사용하는 테 스트케이스의 유지 비용이 지속적으로 발생 가능하다면 설계를 바꿔서라도 Mock 필요없는 의존성 적은 구조로 만드는게 더 좋다 투자 대비 수익이 확실할 때만 사용 Mock을 사용할때는 좀더 길게 볼 필요가 있다 테스트 편의를 위해 사용하기 시작한 Mock객체들이 개발진척의 발목을 잡을수도있다
  • 28. Mock Framework 사용시 유의사항 어떤 Mock 프레임워크를 사용하느냐는 핵심적인 문제가 아니다 유행따라 최고의 Mock 프레임워크를 찾아 떠나는 행동은 하지마라 대부분의 경우 간단한 Mock 객체만으로도 충분하다 Mock은 Mock일 뿐 Mock을 사용한 테스트에서 잘동작해서 실제 객체를 적용해서 잘되리라는 보장은 없다 초반부터 실제객체를 사용 가능하다면 Mock객체를 사용하지 말고 실제객체를 사용해라
  • 29. Q / A
  • 30. END