SlideShare a Scribd company logo
Effective Unit Testing : 개발자를 위한 단위 테스트
초판발행 2013년 11월 10일
지은이 라쎄 코스켈라 / 옮긴이 이복연 / 펴낸이 김태헌
펴낸곳 한빛미디어(주) / 주소 서울시 마포구 양화로 7길 83 한빛미디어(주) IT출판부
전화 02–325–5544 / 팩스 02–336–7124
등록 1999년 6월 24일 제10–1779호 / ISBN 978–89–6848–062–1 13000
책임편집 배용석 / 기획 박민아 / 편집 박민아
디자인 표지 강은영, 내지 강은영, 조판 김현미
영업 김형진, 김진불, 조유미 / 마케팅 박상용, 박주훈, 서은옥
이 책에 대한 의견이나 오탈자 및 잘못된 내용에 대한 수정 정보는 한빛미디어(주)의 홈페이지나 아래 이메일로
알려주십시오. 잘못된 책은 구입하신 서점에서 교환해 드립니다. 책값은 뒤표지에 표시되어 있습니다.
한빛미디어 홈페이지 www.hanb.co.kr / 이메일 ask@hanb.co.kr
Effective Unit Testing: A Guide for Java Developers by Lasse Koskela
Original English language edition published by Manning Publications. USA.
Copyright 2013 by Manning Publications Co..
Korean–language edition copyright 2013 by Hanbit Media, Inc. All rights reserved.
이 책의 한국어판 저작권은 대니홍 에이전시를 통한 저작권사와의 독점 계약으로 한빛미디어㈜에 있습니다.
신저작권법에 의해 한국 내에서 보호를 받는 저작물이므로 무단전재와 복제를 금합니다.
지금 하지 않으면 할 수 없는 일이 있습니다.
책으로 펴내고 싶은 아이디어나 원고를 메일(writer@hanb.co.kr)로 보내주세요.
한빛미디어(주)는 여러분의 소중한 경험과 지식을 기다리고 있습니다.
개발자를 위한 단위 테스트
4
라쎄 코스켈라는 Reaktor 소속의 코치, 트레이너, 컨설턴트, 프로그래머로서 고객이 성공적인
소프트웨어 제품을 만드는 데 이바지하고 있다. 그는 기업용 애플리케이션에서부터 미들웨어
제품까지 다양한 영역의 소프트웨어 프로젝트를 경험해왔다.
공인 스크럼 트레이너(Certified Scrum Trainer)이기도 한 그는 근래에는 고객팀의 생산성
을 개선하고 끊임없이 배워가는 문화를 길러주는 교육 프로그램을 제공하거나 직접 맨토링하
는 데 시간을 쏟고 있다. 또한, 리더와 관리자를 위한 컨설팅 외에도 소프트웨어 개발팀과 일하
며 프로그래밍하는 것 역시 좋아한다.
여가 시간에는 오픈 소스 프로젝트에 참여하거나 소프트웨어 개발 관련 저술 활동을 한다.
직접 블로그(http://lassekoskela.com/thoughts/)도 운영하며, 이번 『Effective Unit
Testing』은 2007년에 출간한 『Test Driven』에 이은 두 번째 작품이다. 그는 핀란드 애자일 커
뮤니티의 선구자 중 한 명으로 국제 컨퍼런스의 발표자로도 자주 얼굴을 비추고 있다.
옮긴이 이복연 wegra.eut@gmail.com
『JUnit in Action: 단위 테스트의 모든 것』(인사이트, 2011)을 번역했다. 고려대학교 컴퓨터
학과를 졸업하고 삼성 소프트웨어 멤버십을 거쳐 삼성 소프트웨어 연구소에 입사했다. 그동안
미디어솔루션센터에서 바다 단말 플랫폼과 소셜허브 개발에 참여했으며, 현재는 클라우드 기
반 서버/인프라 관련 업무를 진행 중이다. 소프트웨어 아키텍처 설계, 애플리케이션 라이프사
이클 관리(ALM), 애자일 등의 분야에 관심이 많다.
지은이 소개
옮긴이 소개
5
제품설계가 요구사항에 달아 소스코드로 서로 사맛디 아니할쌔
이런 전차로 어린 개발자가 검증하고저 홇배 이셔도
마침내 제 뜨들 시러 펴디 몯홇 하니라.
내 이랄 윙하야 어엿비 너겨 새로 책 한 권을 번역하노니
사람마다 해여 수비니겨 날로 쑤메 뼌한키 하고져 할 따라미니라.
처음 이 책을 접했을 때 가장 먼저 눈길을 사로잡았던 것은 바로 『Effective Unit Testing』이
라는 책의 제목과 테스트 가능 설계testable design라는 7장의 제목이었다.
과연 Effective라는 이름을 내걸기에 부끄럽지 않은 책일까? Effective로 시작하는 책 대부분은
유행에 흔들리지 않고 비교적 오랫동안 가치를 인정받는 듬직함을 보여준다. 단순한 따라하기
나 기교 중심의 어떻게how가 아닌, 주제에 관한 깊은 이해와 오랜 경험으로부터 우러나온 왜why
를 다루기 때문이다. 왜를 이해한다는 것은 명확한 목적의식을 가지고 행동하게 되며, 변화하
는 환경에서도 흔들리지 않는 근본적인 기준에 따라 판단하고 응용할 수 있게 됨을 의미한다.
이러한 관점에서 이 책은 전혀 부족하지 않다고 판단되었고 번역 제안을 수락한 결정적인 이유
가 되었다.
개인적으로는 2006년경에 테스트 가능 설계 안티 패턴을 정리하려던 적이 있었다. 홀대받는 테스
트가 사실은 제품 설계와 생산성에 큰 영향을 주므로 개발 초기부터 이를 고려하면 전반적인
개발 과정이 훨씬 효율적이고 부드럽게 진행된다는 점을 알리고 싶었다. 당시만 해도 개척할
게 많은 분야였던 터라 잘 다듬어서 저널이나 학술지에 내볼 요량이었다. 하지만 컨설턴트도
아니고 테스트가 주업도 아닌지라 원하는 만큼의 적절한 예제를 모으는 데 한계가 있었고, 결
옮긴이의 말
6
국 어설픈 초안 수준에서 그만두고 말았다.1
이러한 개인적 경험 때문에 테스트 가능 설계란 주제는 큰 호기심과 아쉬운 감정을 동시에 불러일
으켰다. 그래서 이 책을 통해 내가 정리하던 것과 얼마나 유사한지, 혹은 더 발전했는지 확인해
보고 싶었다. 결국, 구성이나 내용 면에서는 많은 차이를 보였지만 큰 그림과 의도는 일맥상통
했다. 그래서 이렇게 다른 이의 결실에 편승해서라도 그때 하고자 했던 이야기를 세상에 들려
주고 싶다는 동기가 더해졌다.
좋은 설계임을 증명하려거든 자동화된 테스트를 만들어보라!
흔히 실력 좋다고 알려진 개발자 중 많은 수가 무척 복잡하여 어떻게 쓰는지 모르겠는 코드를 내놓거
나 겉은 깔끔하나 그 정도가 지나쳐서 내부 동작원리는 알기 어려운 코드를 만들어내곤 한다. 이런 코드
는 검증하기 어렵다는 치명적인 단점이 있다. 개발자 자신이 시연할 때에는 잘 돌겠지만 다른
모듈과 통합할 시점이 되면, 혹은 제품이 출시된 후 소비자에 의해 다양한 패턴으로 사용되면
서 뒤늦게 문제가 하나씩 터져 나오는 경우가 많다. 단기간에 가시적 결과를 보여줄 수는 있지
만 이렇게 발견된 문제는 개발한 당사자가 아니면 쉽게 손대지 못하니 골치 아픈 상황을 낳기
도 한다. 이들의 능력을 깎아내리려는 의도는 절대 아니다. 다만, 한 차원 높은 생산성과 안정
된 품질, 그리고 동료 개발자도 쉽게 이해하고 배울 수 있는 코드를 작성하는 쉬운 방법이 있으
나 잘 알지 못하는 듯하여 안타까울 뿐이다.
그들에게 필요한 것은 테스트에 대한 인식 전환이다. 테스트란 단순한 기능 검증 수단만이 아
닌 요구사항을 명시한 문장이요, 모듈과 API 설계 수단이며, 사용설명서이자, 최고의 인수인
계/유지보수 자료이기까지 하다. 특히 개발자의 설계역량 면에서 본다면, 디자인 패턴에만 의
지하기보다 테스트하기 쉬운 설계를 추구하는 쪽이 훨씬 탄탄한 기본기와 응용력을 길러줄 것
1 역자주_ http://wegra.org/blog/?page_id=514
7
이라고 감히 단언할 수 있다. 여러분이 이 책을 테스트 지침서가 아닌 설계 지침서로 받아들이고
잘 따라준다면 어느덧 진일보한 자신의 실력에 놀라게 될 것이다.
아무쪼록 독자 여러분께 재미나고 유익한 책이 되길 기원하며, 책 내용 중 혹 궁금한 것이 있거
든 wegra.eut@gmail.com으로 물어봐주시길 바란다. 여건이 허락하는 한 성심껏 답변하도
록 노력하겠다.
마지막으로 휴일까지 반납하며 이 책이 나오기까지 함께 고생해주신 한빛미디어 박민아님, 역
자를 믿고 번역을 맡겨주신 한동훈님, 그리고 이토록 훌륭한 지혜를 공유해준 원서의 저자 라
쎄 코스켈라에게 감사의 마음을 전한다.2
옮긴이_ 이복연
2 편집자주_ 더불어 이 책의 베타리딩에 참여해주신 한빛리더스 이정재님께 감사드립니다.
8
2009년 6월 10일 밤, 매닝Manning의 크리스티나 러들로프Christina Rudloff로부터 한 통의 메일을 받
았다. 그녀는 로이 오쉐로브Roy Osherove의 저서 『The Art of Unit Testing in .NET』1
을 자바Java
에 맞게 다시 써줄 만한 사람을 찾고 있었다. 기꺼이 내가 해주겠노라 답했다.
이건 꽤 오래전의 이야기로, 지금 여러분의 손에 들려 있는 이 책은 로이의 것과는 사뭇 다른
모습이 되었다. 설명을 해보자면 이렇다.
처음에는 .NET을 자바로 단순 변환하는 일로 시작했다. 달라진 플랫폼과 도구만 반영하고 독
자에게 꼭 필요한 부분만 다시 쓰면서 말이다. 1장을 마치고 2장을 마치고 3장까지 써내려 가
다가 문득 하나를 깨달았다. 문장 몇 개 정도가 아니라 한 장chapter 전체를 내가 새로 쓰고 있는
게 아닌가? 문체도 나와 맞지 않았다. 로이와는 다른 방식을 선호하거나 그의 설명에 동의하지
못할 때도 종종 있었다. 여러분에게 따로 꼭 하고 싶은 말이 있거나, 설명을 보충하거나, 기초
부터 확실히 다지고 넘어가고 싶다는 욕심이 강하게 생겨나기도 했다.
결국, 처음부터 새로 시작하기로 했다.
처음 의도했던, 자바 버전에 맞게 쓰는 일을 넘어선 시점이었다. 좋은 테스트를 작성하는 방법
과 주의 사항에 관한 심도 있는 통찰을 통해 자바 프로그래머의 테스트 능력을 키워주는 새롭
고 독특한 책으로 거듭난 것이다. 로이의 생각도 다양한 형태로 이 책에 스며있다. 예컨대 2부
를 구성하는 4, 5, 6장의 이름은 로이의 것을 고스란히 차용했고, 7장도 상당 부분은 로이의 책
『The Art of Unit Testing in.NET』의 관련 내용에 기초하여 썼다.
이 책은 자바 개발자를 위해 쓰였지만, 독자 범위를 인위적으로 제한하고 싶지는 않았다. 비록
2부의 예제 코드는 모두 자바지만, 내용 자체는 언어에 너무 국한되지 않게 하려 노력했다. 좋
은 테스트를 작성하는 방법은 언어와 무관하니 설령 여러분의 주 언어가 자바가 아니더라도 이
1 저자주_ 번역서 『.NET 예제로 배우는 단위 테스트』 (송인철/황인석 역, 인사이트, 2010)
지은이의 말
9
책의 내용을 진지하게 읽어보기를 진심으로 권한다.
같은 맥락에서, 이 책을 JUnit 또는 개인적으로 선호하는 특정 Mock 객체 라이브러리를 배우
기 위한 튜토리얼tutorial로 만들고 싶지 않았다. 시시때때로 변하는 기술, 또는 출판 후 몇 달이
면 폐기될 지식은 배제하고, 나 자신이 정말 읽고 싶은 책을 쓰고 싶었다. 눈 감고도 사용할 만
큼 이미 익숙해져 버린 테스트 프레임워크나 쓰지도 않는 Mock 객체 라이브러리를 억지로 들
이대지 않는 그런 책 말이다. 그래서 특정 기술에 종속된 조언은 최대한 자제하였다. 물론 전혀
없다고 말할 순 없지만, 최선을 다했음을 알아줬으면 한다. 테스트 작성과 실행, 유지보수, 개
선에 빠져서는 안 될 기본적인 개념과 의미 있는 논의가 필요한 정도만을 담아내었다.
다시 한번 말하지만, 나 자신이 읽고 싶은 책을 쓰려고 노력했다. 여러분도 함께 즐겨주길 바라
고, 무엇보다 책 내용 중 일부라도 실천하는 독자가 나와준다면 더 바랄 것이 없다.
지은이_ 라쎄 코스켈라
10
대상 독자
이 책은 개발 경험의 많고 적음을 떠나 단위 테스트의 품질을 높이고자 하는 모든 자바 프로그
래머를 위해 쓰였다. 부록에 JUnit 테스트 프레임워크 사용법을 넣긴 했지만, 책의 주목적은
이미 테스트 프레임워크를 하나쯤 사용할 줄 아는 자바 프로그래머가 더 좋은 테스트를 만들도
록 이끌어주는 것이다. 여러분이 지금껏 작성한 테스트가 아무리 많더라도, 더 발전할 가능성
은 아직 남아 있다고 확신한다. 더불어 이 책은 그동안 명확하게 정립되지 못한 채 여러분 머릿
속에만 떠돌던 많은 생각을 자극해줄 것이다.
로드맵
『Effective Unit Testing』은 하나로 아울러 다루기에는 적합하지 않은 다각적인 문제를 다루
고 있다. 그래서 여러 차례 실패를 거듭한 끝에 책을 크게 세 부분으로 나눠 구성하는 것이 가
장 좋겠다는 결론을 얻었다.
긴 여정의 시작을 알리는 1부는 우리가 이루고자 하는 목적과 이를 프로젝트 초기부터 고려해
야 하는 이유를 알려준다. 좋은 테스트를 작성하기 위해 꼭 필요한 도구와 간단한 지침을 포함
하여 총 세 개의 장으로 구성했다.
1장에서는 자동화된 단위 테스트의 가치를 역설한다. 프로그래머 생산성에 영향을 주는 여러
요소를 생각해보고, 잘 작성된 자동화된 테스트가 생산성에 어떻게 이바지하는지 혹은 기운 빠
지는 일을 예방해주는지를 설명한다.
2장에서는 좋은 테스트의 조건을 정의한다. 여기에서 살펴볼 속성은 2부에서 본격적으로 다룰
테스트의 가독성, 유지보수성, 신뢰성을 이해하기 위한 기초 개념이다.
잠시 숨도 돌릴 겸, 3장에서는 좋은 테스트를 작성하기 위한 필수 도구인 테스트 더블을 소개
한다. 테스트 더블을 그저 사용할 줄 아는 것보다는, 주의해서 올바르게 활용할 줄 아는 것이
목표다. 테스트 더블이 만병통치약은 아니기 때문이다.
이 책에 대하여
11
2부에서는 주의해야 할 테스트 냄새1
를 쭉 나열한다. 테스트 작성 시 경계해야 할 패턴을 설명
하고, 그런 낌새를 느꼈을 때 적용할 수 있는 해결책을 제시할 것이다. 세부 주제는 크게 3개
다. 가독성을 떨어뜨리는 냄새, 잠재적으로 유지보수 악몽을 일으키는 냄새, 마지막은 신뢰성
을 떨어뜨리는 냄새다. 사실 여기서 다루는 냄새 중 상당수는 세 범주 어디에나 속할 수 있지
만, 그중 가장 두드러지는 효과가 무엇이냐를 기준으로 배치했다.
4장에서는 테스트 의도나 구현을 모호하게 하는 냄새를 집중적으로 공략한다. 테스트 코드 속
의 판독하기 어려운 단언문, 적절치 못한 추상화, 흩어진 정보 등을 다루게 된다.
5장에서는 끊임없는 야근을 강요하는 테스트 냄새를 살펴본다. 엉망으로 작성한 단위 테스트
는 조금만 손보려 해도 끝도 없는 수정을 유발하기도 하고, 사소한 수정 하나가 수백 개의 다른
테스트까지 고쳐야 하는 상황을 초래하기도 한다. 그리하여 테스트에서의 코드 중복, 조건부
로직, 그리고 파일시스템을 건드렸을 때의 악몽을 자세히 설명한다. 테스트 속도를 느려지게
하는 냄새도 여기 포함된다. 시간은 돈이다.
테스트 냄새의 마지막인 6장에서는 잘못된 가정 때문에 고생했던 경험으로부터 깨달은 지혜를
공유한다. 테스트 코드에 잘못 쓰인 주석 때문에, 혹은 우리 자신의 의도를 분명하게 표현하지
못해서 생겨난 가정을 살펴볼 것이다.
3부의 제목은 자칫 고급 주제가 될 뻔했다. 하지만, 1부와 2부의 내용을 숙지하지 않았더라도 자
바 개발자가 테스트를 작성하며 언제든 살펴볼 수 있는 주제다. 결국 좋은 단위 테스트를 만드
는 조건은 거의 예외 없이 우리가 처한 상황에 따라 달라진다. 그래서 어떤 프로그래머에게 아
주 시급한 주제가 다른 이에게는 하찮은 문제라 해도 전혀 놀랄 일이 아니다. 테스트 클래스의
상속 관계나 테스트 작성에 쓰인 프로그래밍 언어 혹은 빌드 인프라가 테스트를 실행하는 방식
에 기인한 문제 등 그 어떤 것도 예외는 아니다.
1 역자주_ 테스트 냄새란 테스트 코드에서 주로 나타나는 코드 냄새다. 즉 테스트를 이해하고 관리하기가 어렵다거나 결과의 정확성이 떨어
지는 등 개선의 여지가 있을 수 있다는 징후다.
12
7장에서는 2장에서 미처 다루지 못했던 테스트 가능 설계를 만드는 요소로 꾸며보았다. 유용한
원칙 몇 개와 우리가 생각하는 이상적인 모듈화 설계에 관해서 간략히 훑고, 테스트 불가 설계
라는 기본적인 테스트 가능성 문제를 공부한다. 마지막으로는 테스트 가능 설계로 이끌어줄 간
단한 지침을 준비해두었다.
8장에서는 ‘단위 테스트를 자바가 아닌 언어로 작성하고 싶다면?’이라는 질문으로 시작한다.
오늘날의 자바 가상 머신에서는 자바 외에도 수많은 언어를 사용할 수 있고 순수 자바 코드와
연동하는 것도 가능하다.
9장에서는 서서히 느려지는 빌드 속도와 그와 함께 늦어지는 피드백 주기라는, 현실에서 흔하
게 겪는 상황을 고민해본다. 테스트 코드와 인프라, 즉 안팎 모두에서 돌파구를 찾아보았다. 코
드 측면에서는 실행 속도를 개선하는 방법을, 인프라 측면에서는 더 빠른 하드웨어를 도입하는
것, 혹은 기존 하드웨어를 그대로 두고 작업 할당 방식을 바꿔보는 방법 등을 살펴본다.
JUnit의 독보적인 명성과 업계 표준 단위 테스트 프레임워크라는 위치에도 불구하고, 모든 자
바 프로그래머가 이에 익숙한 것은 아니다. 그래서 JUnit의 진보된 기능을 충분히 활용하지 못
했던 독자를 위해 부록 두 개를 수록해뒀다.
부록 A에서는 JUnit을 이용하여 테스트를 작성하고 실행하는 방법을 간단히 설명한다. 이 부록
을 읽고 나면 JUnit API를 활용해서 테스트를 만들고 단언문을 쓰기가 한층 수월해질 것이다.
부록 B는 JUnit의 기능을 확장할 때 필요한 API라는 다소 깊이 있는 주제를 다룬다. JUnit의
상세 내용을 전부 다루겠다는 욕심은 없고, 단지 확장 시에 가장 일반적으로 쓰이는 두 가지 방
법인 규칙rule과 러너runner를 소개하고, 기본 규칙 몇 개를 선보이는 선에서 마무리하려 한다. 이
규칙은 그 자체로도 물론 유용하지만, 사용자 확장을 통해 어떤 일까지 더 할 수 있을지 감을
잡아줄 것이다.
코드 작성 규칙 및 소스코드 내려받기
이 책에 등장하는 코드 예제에는 자바 소스코드, 마크업 언어, 출력 리스트가 있다. 길이가 길
13
어지면 이름(헤더)을 붙여 별도의 코드로 제공하고, 짧은 코드는 본문 안에 그대로 두었다. 모
든 예제는 고정폭 글꼴로 표기하여 본문과 구분했다. 긴 코드에서는 본문에서 참조하기 좋도록
번호 붙은 주석을 사용하기도 한다.
소스코드는 www.hanb.co.kr/exam/2062에서 내려받을 수 있다. 책에서 선별한 소스코드
만 담아 놨으니, 여러분이 그 이상으로 발전시켜보기 바란다.
예제 코드는 자바 6로 작성했으니 호환 버전을 설치하기 바란다. 필요한 자바 환경은 www.
oracle.com에서 받을 수 있다. 컴파일까지 해보려면 JRE가 아닌 JDK를 설치하는 걸 잊지
말자.
선호하는 IDE도 설치해두면 편하다. 최신 버전의 이클립스2
나 IntelliJ 아이디어(IDEA,
www.jetbrains.com), 넷빈즈3
중 가장 마음에 드는 것을 설치하자. 여러분 손에 익은 도구
라면 무엇을 선택하건 상관없다.
책을 다 읽은 후엔?
이 책에서 얻은 통찰로 여러분의 단위 테스트는 눈에 띄게 향상될 것이다. 물론 긴 여정이 될
것이고 우리가 예측하지 못했거나 완벽히 답하지 못한 질문이 한두 개 나올 수 있다. 다행히도
그 여정에는 수많은 친구가 함께할 것이고, 그중 많은 이들이 테스트 코드의 미묘한 차이를 주
제로 기꺼이 토론하고 공유할 것이다.
매닝에서는 매닝의 저자와 이야기할 수 있는 온라인 포럼을 마련해두고 있다. 이 책도 마찬
가지다. www.manning.com/EffectiveUnitTesting에 열어둔 저자 온라인 포럼을 방문해
보자.
Yahoo! Groups의 testdrivendevelopment와 extremeprogramming은 테스트 추종 프로
2 저자주_ Eclipse, www.eclipse.org
3 저자주_ NetBeans, www.netbeans.org
14
그래머 간의 논의가 끊이지 않는 포럼이다. 단위 테스트만 다루는 포럼은 아니지만, 관련 주제
를 논하기에 훌륭한 장소다. 테스트 코드 외적인 새로운 생각도 접할 좋은 기회가 될 것이다.
개발자 테스트에 더 충실한 포럼을 찾는다면 http://www.coderanch.com의 CodeRanch
를 방문해서 Testing 포럼을 찾아보라. 이곳에서도 좋을 사람을 많이 사귈 수 있을 것이다.
하지만, 여러분이 짠 테스트 코드를 놓고 옆의 동료와 적극적으로 토론해보는 것이 그 무엇보
다도 더 효율적인 실천법임을 말해두고 싶다. 개인적으로도 옆에서 함께 고민하던 동료가 나의
코드에 대한 최고의 통찰을 일깨워준 경우가 많다.
15
『Effective Unit Testing』 표지 그림의 제목은 크로아티아 달마티아 드리니스에서 온 사내A Man from
Drnis, Dalmatia, Croatia다. 이 그림은 니콜라 아르세노비크Nikola Arsenovic가 2003년 크로아티아의 민족
학 박물관Ethnographic Museum을 통해 출간한, 19세기 중반 이후 크로아티아인의 전통 복장을 담은
앨범에서 빌려 왔다. 그 책에는 크로아티아의 다른 지역의 복식과 일상생활에 관해서도 정밀
하게 채색된 삽화를 곁들여 설명하고 있다. 한편, 이 박물관은 AD 304년경 디오클레티아누스
Diocletian 황제가 퇴임 후 지냈던 궁전의 잔해가 위치한 로마의 중세 도시 안에 지어졌다.
드리니스drnis는 중세 고성의 잔해 위에 세워진 달마티아Dalmatia 섬의 작은 마을이다. 표지 그림
의 사내는 푸른색 울wool 바지와 하얀 섬유 셔츠, 지역 전통 복장이었던 색색의 자수가 놓인 푸
른색 울 조끼를 입고 있다. 손에는 긴 파이프를 들고 어깨에는 진홍빛 재킷을 대충 걸치고 있
다. 그리고 빨간 모자와 가죽 모카신moccasin으로 복장을 완성했다.
앨범 속의 시대 이후 200여 년이 흐르면서, 변화하는 복장 규정과 생활 양식에 맞춰 다채롭던
지역색도 점차 퇴색되었다. 이제는 몇 마일 떨어지지 않은 작은 마을이나 도시 사람은 말할 것
도 없고, 심지어 다른 대륙에 사는 사람 간에도 차이가 크지 않다. 우리는 아마도 문화와 외향
적 다양성을 더 다양하고 빠르게 변모하는 첨단 기술 생활이라는 개인의 다양성과 맞바꾸어 왔
으리라.
매닝은 2세기 전의 풍성했던 지역적 다양성을 빌려 컴퓨터 사업의 독창성과 창의력을 찬미하
고자, 이처럼 오래된 책과 모음집의 삽화를 다시 세상 밖으로 끄집어내어 표지 그림으로 활용
하고 있다.
표지 설명
16
CONTENTS
옮긴이 소개 ....................................................................................................................
4
지은이 소개 ....................................................................................................................
4
옮긴이의 말 ....................................................................................................................
5
지은이의 말 ....................................................................................................................
8
이 책에 대하여 ..............................................................................................................
10
표지 설명 .....................................................................................................................
15
PART 1 기반 다지기
CHAPTER 1 좋은 테스트의 약속
1.1 더 좋은 테스트를 작성하기 위한 현황 점검 .........................................................................
29
1.2 테스트의 가치 ...............................................................................................................
30
1.2.1 생산성에 영향을 주는 요소 ......................................................................................
34
1.2.2 설계 잠재력 곡선 ...................................................................................................
36
1.3 설계 수단으로써의 테스트 ...............................................................................................
37
1.3.1 테스트 주도 개발 ...................................................................................................
37
1.3.2 행위 주도 개발 ......................................................................................................
39
1.4 요약 ............................................................................................................................
41
CHAPTER 2 좋은 테스트란?
2.1 읽기 쉬운 코드가 유지보수도 쉽다 ....................................................................................
45
2.2 구조화가 잘 되어 있다면 이해하기 쉽다 .............................................................................
47
2.3 엉뚱한 걸 검사하는 건 좋지 않다 ......................................................................................
50
2.4 독립적인 테스트는 혼자서도 잘 실행된다 ...........................................................................
51
17
2.5 믿음직한 테스트라야 기댈 수 있다 ....................................................................................
54
2.6 모든 일이 그렇듯 테스트에도 도구가 쓰인다 .......................................................................
56
2.7 요약 ............................................................................................................................
57
CHAPTER 3 테스트 더블
3.1 테스트 더블의 위력 ........................................................................................................
61
3.1.1 테스트 대상 코드를 격리한다 ...................................................................................
62
3.1.2 테스트 속도를 개선한다 ..........................................................................................
64
3.1.3 예측 불가능한 실행 요소를 제거한다 .........................................................................
64
3.1.4 특수한 상황을 시뮬레이션한다 .................................................................................
65
3.1.5 감춰진 정보를 얻어낸다 ..........................................................................................
66
3.2 테스트 더블의 종류 ........................................................................................................
68
3.2.1 테스트 스텁은 유난히 짧다 ......................................................................................
68
3.2.2 가짜 객체는 뒤끝 없이 처리한다 ...............................................................................
70
3.2.3 테스트 스파이는 기밀을 훔친다 ................................................................................
71
3.2.4 Mock 객체는 예기치 않은 일을 막아준다 ..................................................................
74
3.3 테스트 더블 활용 지침 ....................................................................................................
76
3.3.1 용도에 맞는 더블을 선택하라 ...................................................................................
76
3.3.2 준비하고, 시작하고, 단언하라 ...................................................................................
77
3.3.3 구현이 아니라 동작을 확인하라 ................................................................................
78
3.3.4 자신의 도구를 선택하라 ..........................................................................................
79
3.3.5 종속 객체를 주입하라 .............................................................................................
80
3.4 요약 ............................................................................................................................
81
18
PART 2 테스트 냄새
CHAPTER 4 가독성
4.1 기본 타입 단언 ..............................................................................................................
87
4.1.1 예시 ....................................................................................................................
87
4.1.2 개선 방법 .............................................................................................................
88
4.1.3 정리 ....................................................................................................................
90
4.2 광역 단언 .....................................................................................................................
91
4.2.1 예시 ....................................................................................................................
91
4.2.2 개선 방법 .............................................................................................................
94
4.2.3 정리 ....................................................................................................................
96
4.3 비트 단언 .....................................................................................................................
96
4.3.1 예시 ....................................................................................................................
97
4.3.2 개선 방법 .............................................................................................................
98
4.3.3 정리 ....................................................................................................................
98
4.4 부차적 상세정보 ............................................................................................................
99
4.4.1 예시 ....................................................................................................................
99
4.4.2 개선 방법 ...........................................................................................................
101
4.4.3 정리 ..................................................................................................................
103
4.5 다중 인격 ...................................................................................................................
103
4.5.1 예시 ..................................................................................................................
104
4.5.2 개선 방법 ...........................................................................................................
104
4.5.3 정리 ..................................................................................................................
108
4.6 쪼개진 논리 ................................................................................................................
108
4.6.1 예시 ..................................................................................................................
109
4.6.2 개선 방법 ...........................................................................................................
111
CONTENTS
19
4.6.3 정리 ..................................................................................................................
114
4.7 매직 넘버 ...................................................................................................................
115
4.7.1 예시 ..................................................................................................................
115
4.7.2 개선 방법 ...........................................................................................................
116
4.7.3 정리 ..................................................................................................................
117
4.8 셋업 설교 ...................................................................................................................
117
4.8.1 예시 ..................................................................................................................
118
4.8.2 개선 방법 ...........................................................................................................
119
4.8.3 정리 ..................................................................................................................
121
4.9 과잉보호 테스트 ..........................................................................................................
121
4.9.1 예시 ..................................................................................................................
122
4.9.2 개선 방법 ...........................................................................................................
123
4.9.3 정리 ..................................................................................................................
123
4.10 요약 ........................................................................................................................
123
CHAPTER 5 유지보수성
5.1 중복 ..........................................................................................................................
127
5.1.1 예시 ..................................................................................................................
127
5.1.2 개선 방법 ...........................................................................................................
128
5.1.3 정리 ..................................................................................................................
131
5.2 조건부 로직 ................................................................................................................
131
5.2.1 예시 ..................................................................................................................
132
5.2.2 개선 방법 ...........................................................................................................
133
5.2.3 정리 ..................................................................................................................
134
5.3 양치기 테스트 .............................................................................................................
134
5.3.1 예시 ..................................................................................................................
135
5.3.2 개선 방법 ...........................................................................................................
136
20
5.3.3 정리 ..................................................................................................................
138
5.4 파손된 파일 경로 .........................................................................................................
138
5.4.1 예시 ..................................................................................................................
139
5.4.2 개선 방법 ...........................................................................................................
140
5.4.3 정리 ..................................................................................................................
142
5.5 끈질긴 임시 파일 .........................................................................................................
143
5.5.1 예시 ..................................................................................................................
143
5.5.2 개선 방법 ...........................................................................................................
144
5.5.3 정리 ..................................................................................................................
146
5.6 잠자는 달팽이 .............................................................................................................
147
5.6.1 예시 ..................................................................................................................
147
5.6.2 개선 방법 ...........................................................................................................
148
5.6.3 정리 ..................................................................................................................
150
5.7 픽셀 퍼펙션 ................................................................................................................
151
5.7.1 예시 ..................................................................................................................
151
5.7.2 개선 방법 ...........................................................................................................
153
5.7.3 정리 ..................................................................................................................
157
5.8 파라미터화된 혼란 .......................................................................................................
158
5.8.1 예시 ..................................................................................................................
158
5.8.2 개선 방법 ...........................................................................................................
162
5.8.3 정리 ..................................................................................................................
165
5.9 메서드 간 응집력 결핍 ..................................................................................................
166
5.9.1 예시 ..................................................................................................................
166
5.9.2 개선 방법 ...........................................................................................................
168
5.9.3 정리 ..................................................................................................................
171
5.10 요약 ........................................................................................................................
172
CONTENTS
21
CHAPTER 6 신뢰성
6.1 주석으로 변한 테스트 ...................................................................................................
177
6.1.1 예시 ..................................................................................................................
177
6.1.2 개선 방법 ...........................................................................................................
178
6.1.3 정리 ..................................................................................................................
179
6.2 오해를 낳는 주석 .........................................................................................................
180
6.2.1 예시 ..................................................................................................................
180
6.2.2 개선 방법 ...........................................................................................................
181
6.2.3 정리 ..................................................................................................................
183
6.3 절대 실패하지 않는 테스트 ............................................................................................
183
6.3.1 예시 ..................................................................................................................
184
6.3.2 개선 방법 ...........................................................................................................
184
6.3.3 정리 ..................................................................................................................
185
6.4 지키지 못할 약속 .........................................................................................................
186
6.4.1 예시 ..................................................................................................................
186
6.4.2 개선 방법 ...........................................................................................................
189
6.4.3 정리 ..................................................................................................................
190
6.5 낮아진 기대치 .............................................................................................................
191
6.5.1 예시 ..................................................................................................................
191
6.5.2 개선 방법 ...........................................................................................................
193
6.5.3 정리 ..................................................................................................................
193
6.6 플랫폼 편견 ................................................................................................................
194
6.6.1 예시 ..................................................................................................................
194
6.6.2 개선 방법 ...........................................................................................................
195
6.6.3 정리 ..................................................................................................................
198
6.7 조건부 테스트 .............................................................................................................
198
6.7.1 예시 ..................................................................................................................
199
22
6.7.2 개선 방법 ...........................................................................................................
200
6.7.3 정리 ..................................................................................................................
201
6.8 요약 ..........................................................................................................................
201
PART 3 여흥거리
CHAPTER 7 테스트 가능 설계
7.1 테스트 가능 설계란? ....................................................................................................
207
7.1.1 모듈러 설계 ........................................................................................................
208
7.1.2 SOLID 설계 원칙 ................................................................................................
209
7.1.3 맥락을 고려한 모듈러 설계 ....................................................................................
211
7.1.4 모듈러 설계를 위한 시운전 ....................................................................................
211
7.2 테스트 불가 원인 .........................................................................................................
212
7.2.1 클래스 생성 불가 .................................................................................................
212
7.2.2 메서드 호출 불가 .................................................................................................
213
7.2.3 결과 확인 불가 ....................................................................................................
214
7.2.4 협력 객체 대체 불가 .............................................................................................
214
7.2.5 메서드 오버라이딩 불가 ........................................................................................
215
7.3 테스트 가능 설계를 위한 지침 ........................................................................................
216
7.3.1 복잡한 private 메서드를 피하라 .............................................................................
216
7.3.2 final 메서드를 피하라 ...........................................................................................
216
7.3.3 정적 메서드를 피하라 ...........................................................................................
217
7.3.4 new는 신중하게 사용하라 ....................................................................................
218
7.3.5 생성자에서는 로직 구현을 피하라 ...........................................................................
219
7.3.6 싱글톤을 피하라 ..................................................................................................
221
CONTENTS
23
7.3.7 상속보다는 컴포지션을 사용하라 ............................................................................
223
7.3.8 외부 라이브러리를 감싸라 .....................................................................................
223
7.3.9 서비스 호출을 피하라 ...........................................................................................
224
7.4 요약 ..........................................................................................................................
226
CHAPTER 8 제2의 JVM 언어를 활용한 테스트 작성
8.1 JVM 언어 혼용의 조건 .................................................................................................
231
8.1.1 일반적인 이점 .....................................................................................................
231
8.1.2 테스트 작성하기 ..................................................................................................
234
8.2 그루비로 단위 테스트 작성하기 ......................................................................................
235
8.2.1 간소화된 테스트 셋업 ...........................................................................................
236
8.2.2 그루비로 작성한 JUnit 4 테스트 ............................................................................
238
8.3 BDD 도구의 뛰어난 표현력 ...........................................................................................
240
8.3.1 easyb로 작성한 그루비 명세 .................................................................................
240
8.3.2 테스트의 표현력을 높여주는 스폭 ...........................................................................
242
8.3.3 스폭의 또 다른 무기, 테스트 더블 ...........................................................................
244
8.4 요약 ..........................................................................................................................
246
CHAPTER 9 테스트 속도 개선
9.1 속도 개선을 위해서 ......................................................................................................
251
9.1.1 더 빠르게! ..........................................................................................................
251
9.1.2 상황 속으로 ........................................................................................................
252
9.1.3 빌드 프로파일링하기 ............................................................................................
252
9.1.4 테스트 프로파일링하기 .........................................................................................
256
9.2 테스트 코드 속도 높이기 ...............................................................................................
259
24
9.2.1 피곤하지 않다면 잠들지 말라 .................................................................................
260
9.2.2 덩치 큰 기반 클래스를 경계하라 .............................................................................
260
9.2.3 불필요한 셋업과 티어다운을 경계하라 .....................................................................
263
9.2.4 테스트에 초대할 손님은 까다롭게 선택하라 ..............................................................
265
9.2.5 로컬하게, 그리고 빠르게 유지하라 ..........................................................................
266
9.2.6 데이터베이스의 유혹을 뿌리쳐라 ............................................................................
268
9.2.7 파일 I/O보다 느린 I/O는 없다 ................................................................................
269
9.3 빌드 속도 높이기 .........................................................................................................
272
9.3.1 램 디스크를 활용한 초고속 I/O ..............................................................................
273
9.3.2 빌드 병렬화하기 ..................................................................................................
274
9.3.3 고성능 CPU에 짐 떠넘기기 ...................................................................................
280
9.3.4 빌드 분산하기 .....................................................................................................
283
9.4 요약 ..........................................................................................................................
288
Appendix 부록
Appendix A JUnit 기초
A.1 기본적인 JUnit 테스트 케이스 .................................................................................
293
A.2 JUnit 단언문 ........................................................................................................
295
Appendix B JUnit 확장하기
B.1 러너를 통해 테스트 동작 제어하기 ............................................................................
301
B.2 규칙으로 테스트 꾸미기 ..........................................................................................
303
B.3 기본 규칙들 ..........................................................................................................
303
CONTENTS
25
기반 다지기
Part I
1부는 여러분과의 첫 대면임을 생각해서 서로 간의 공감대를 확고히 형성하기 위한 내용으로 꾸며보았다. 이
책의 궁극적인 목표인 ‘좋은 테스트를 작성하는 능력 키우기’를 위한 첫 과정으로, 1장에서는 테스트를 작성해
서 얻을 수 있는 이점이 무엇인지 살펴본다. 이어서 프로그래머 생산성에 영향을 주는 요소를 알아보고, 그중
에서 특히 테스트와 테스트 품질이 미치는 영향에 관해 집중적으로 이야기할 것이다. 마무리로는 자동화된 테
스트와 밀접한 주제인 ‘테스트 주도 개발’(TDD)과 ‘행위 주도 개발’(BDD)을 소개하겠다.
2장에서는 좋은 테스트가 갖춰야 할 요건을 정의한다. 간단히 말해 가독성, 유지보수성, 신뢰성이 우수한 테스
트를 작성해야 한다. 이 주제는 2부에서 더 깊게 다뤄지는데, 원치 ‘않는’ 모습의 테스트라는 다른 관점에서 바
라본 예제를 검토하게 될 것이다.
1부의 마지막인 3장에서는 오늘날 프로그래머의 필수 도구로 떠오른 테스트 더블을 배워본다. 먼저, 테스트
더블로 할 수 있는 일을 알아본다. 예를 들어 테스트를 효율적으로 하기 위해 테스트 더블로 코드를 격리할 수
있다. 이어서 우리가 사용할 수 있는 테스트 더블의 종류별 차이점을 알아본다. 마지막으로는 테스트 더블의
장점을 최대한 살릴 수 있는 올바른 활용 지침을 준비하였다.
1부를 모두 읽고 나면 여러분이 작성하고 싶은 테스트의 모습과 그렇게 만들고 싶은 이유가 머릿속에 그려질
것이다. 더불어 그런 테스트를 만들 때 유용한 테스트 더블도 명확하게 이해하게 될 것이다. 이상의 기반을 토
대로 나머지 2부와 3부에서는 실무에 바로 활용할 수 있는 기술과 비법을 한 아름 안겨줄 것이다.
27
좋은 테스트의 약속
CHAPTER
1
이 장의 내용
● 단위 테스트의 가치
● 개발자 생산성을 향상하는 테스트
● 설계 도구로써의 테스트
28 Part I 기반 다지기
내가 전문 프로그래머로 사회에 첫발을 내디뎠을 때만 해도 지금과는 사뭇 다른 세상이었다. 바
야흐로 10년도 더 지난 과거의 이야기다. 사람들은 이클립스Eclipse나 넷빈즈NetBeans, 아이디어IDEA
와 같은 통합 개발 환경이 아닌 빔Vim이나 이맥스Emacs 같은 텍스트 편집기로 코드를 작성하고
있었다. 이맥스 매크로를 마구 휘둘러 수천, 수만의 System.out.println 문을 생성해대며 디
버깅하던 직장 선배의 모습이 아직도 눈에 선하다. 그리고 주문이 제대로 처리되지 않는 버그
덕분에, 그 많은 println이 내뱉은 로그를 해독하느라 고생하던 나의 모습은 더욱 생생하다.
프로그래머 대부분이 테스트를 코딩이 끝나면 다른 사람이 해주는 일 혹은 코딩을 다 끝냈다고
선언하기 전에 자신이 짠 코드를 이리저리 찔러보는 일 정도로 치부하던 시절이다. 그러다가
버그가 발견되면, 잘못된 곳을 찾기 위해 로그를 조금씩 추가하며 코드를 들쑤시는 모습이 친
근한 일상이었다.
자동화는 당시의 우리에게는 신선한 개념이었다. 컴파일과 패키징 정도는 메이크파일makefile로
자동화해뒀지만, 빌드할 때마다 테스트까지 함께 돌리지는 않았다. 그 대신에 한두 개의 테스
트 클래스를 실행하는 셸 스크립트를 여러 개 만들어 썼다. 테스트 클래스라고는 했지만, 사실은
제품 코드를 실행해서 결과를 화면에 뿌려주는 간단한 애플리케이션에 지나지 않았다. 실패한
단언 모두를 알려주는 오늘날의 테스트 프레임워크와 자가검증self-verifying 테스트와는 비교할 바
가 못 된다.
그 후로 많은 시간이 흘렀다.
좋은 테스트의 약속
CHAPTER 1
29CHAPTER 1 좋은 테스트의 약속
1.1 더 좋은 테스트를 작성하기 위한 현황 점검
자동화된 테스트는 개발자가 직접 작성해야 하고, 그중 하나라도 실패하면 빌드 전체가 실패한
것이란 인식은 이제 꽤 널리 퍼져있다. 나아가, 테스트 선행 방식의 프로그래밍을 실천하는 개
발자 수도 점점 늘고 있다. 테스트 선행 방식에서는 자동화된 테스트를 단순한 오류 예방 목적
으로뿐 아니라, 코딩 전에 그 코드에 기대하는 동작을 정의하는 설계 보조 수단으로까지 활용
한다. 구현까지 다 끝나야 검증을 시작하는 게 아니라 애초에 설계부터 검증하고 들어가는 것
이다.
개인적으로는 컨설턴트로 활동하면서 수많은 팀과 조직, 제품, 코드를 접해왔다. 그런데 요즘 주
변을 둘러보면 자동화된 테스트는 이미 주류로 편입된 것이 확실하다. 자동화된 테스트 없이는
대부분의 소프트웨어 프로젝트의 상황이 지금보다 훨씬 열악했을 것이 분명하니 확실히 올바
른 길로 나아가는 중이다. 자동화된 테스트는 여러분의 생산성을 높이고 개발 속도를 빠른 상
태로 유지해준다.1
도와줘! 단위 테스트는 처음이란 말이야.
자동화된 테스트 작성에 익숙하지 않은 독자라면 바로 지금이 배울 수 있는 절호의 기회다. 매닝(Manning)에
서는 자바 단위 테스트계의 사실상 표준 프레임워크인 JUnit 관련 책을 다수 내놓았다. 그중에서도 『JUnit in
Action』1
은 POJO(Plain Old Java Object)부터 엔터프라이즈 자바빈즈(Enterprise JavaBeans)에 이르는
온갖 자바 코드를 테스트하는 방법을 가르쳐주는 훌륭한 참고서가 될 것이다.
자바와 JUnit만 처음일 뿐 단위 테스트 자체는 좀 작성해보았다면 ‘부록 A - JUnit 기초’를 가볍게 훑어보는
정도면 이 책에 담긴 지혜를 모두 얻어가는 데 부족함은 없을 거다.
자동화된 테스트가 널리 퍼졌다고 해서 테스트 커버리지가 매우 높다거나 개발 생산성을 더 이
상 끌어올리기 어렵다는 의미는 절대 아니다. 사실 나는 지난 5년여 동안 다른 개발자에게 테
스트를 작성하게 하고, 구현에 앞서 테스트부터 만들게 했으며, 특히 더 좋은 테스트를 작성하
게 도와주며 많은 시간을 보냈다.
테스트를 더 잘 작성해야 한다고 이토록 강조하는 이유는 뭘까? 테스트 품질을 등한시하면 어
떤 일이 벌어질까? 이제부터 테스트가 주는 가치와 테스트 품질의 중요성에 관하여 본격적으
1 저자주_ 피터 타치브 등, 매닝, 2010.
번역서 『JUnit in Action 단위 테스트의 모든 것』 (이복연 역, 인사이트, 2011)
30 Part I 기반 다지기
로 이야기를 시작해보겠다.
1.2 테스트의 가치
촉망받는 프로그래머 마커스를 소개한다. 그는 2년 전에 대학을 졸업하고, 지역 투자 은행의
IT 부서에 입사하여 온라인 셀프서비스 웹 애플리케이션을 개발해왔다. 입사 초기에는 팀의 막
내로서 은행 관련 지식을 쌓고 선배들이 일하는 방식을 파악하는 데 힘썼다.
입사 후 몇 달도 채 지나지 않아, 마커스는 팀이 프로그래머의 실수2
를 바로잡기 위한 재작업에
상당한 시간을 허비하고 있다는 사실을 알아차렸다. 지금껏 수정해온 실수의 유형을 주의 깊게
살펴보니, 그 대부분은 간단한 단위 테스트만으로도 쉽게 잡을 수 있을 것 같았다. 그래서 마커
스는 실수하기 쉬워 보이는 코드를 찾아 이곳저곳에 단위 테스트를 작성해 넣기 시작했다.
테스트는 실수를 바로잡아준다.
시간이 흐르자 다른 팀원 역시 서서히 단위 테스트를 작성하기 시작했다. 마커스는 이른바 테스
트 추종자3
가 되었고, 그가 작성한 코드 대부분은 자동화된 테스트로 매우 높은 커버리지를 달성
하였다. 오류 수정에 쏟는 시간이 늘어난 것도 아닌데 미해결 결함의 수는 점차 줄어들었다. 테
스트가 팀의 작업 품질에 가시적인 영향을 주기 시작한 것이다.
마커스가 코드베이스에 첫 번째 테스트를 추가한 이후로 근 1년이 흘렀다. 마커스는 크리스마
스 파티 장소로 향하며 지금까지 경험한 변화를 되짚어보았다. 그런데 팀 전체의 테스트 커버리
지는 계속 빠르게 상승해오다가 최근 몇 주에서 몇 달간은 98%를 정점으로 큰 변화가 없었다.
마커스는 한동안 이 수치를 100%까지 끌어올려야 한다는 생각에 사로잡혀 있었다. 하지만 최
근 몇 주 사이에 마음을 바꿔먹었다. 아직 채워지지 않은 테스트가 가져다줄 가치가 그리 크지
않아서 테스트 작성에 힘을 더 쏟아봤자 돌아오는 소득이 별로 없어 보였다. 아직 검증되지 않
은 코드는 마커스 팀에서는 사용하지 않는 인터페이스를 구현해야 하는 API가 대부분이었다.
이런 껍데기 메서드를 검사해서 무엇하겠는가?
2 저자주_ ‘오류(error)’, ‘결함(defect)’, ‘버그(bug)’, ‘문제(issue)’라고도 한다.
3 저자주_ 테스트 추종자(test-infected)란 용어는 1998년 Java Report에 실린 에릭 감마(Erich Gamma)와 켄트 벡의 기고문
『Test-Infected: Programmers Love Writing Tests』 (테스트 추종자: 테스트 작성을 사랑하는 프로그래머들)에서 처음 사용되었다.
31CHAPTER 1 좋은 테스트의 약속
100% 코드 커버리지 달성이 중요한 게 아니다.
95%보다는 100%가 물론 듣기 좋다. 다만, 그 차이는 그리 크지 않을 수 있다. 테스트의 가치는 테스트가 확인
하지 못한 코드가 어떤 것인가와 테스트가 프로그래밍 실수를 얼마나 정확하게 잡아내는가에 좌우된다. 100%
를 달성했다고 해서 결함이 없다고 보장해주는 건 아니다. 애플리케이션 동작이 올바른가와는 상관없이, 그저 모
든 코드를 한 번씩은 실행해보았다는 것만을 보장할 뿐이다. 그러니 커버리지에 대한 강박관념은 버리고 의미 있
는 테스트를 작성하는 데 집중하기 바란다.
그림 1-1 테스트 수가 많아질수록 새로 추가한 테스트의 가치는 떨어진다. 왜냐하면, 개발자
는 일반적으로 가장 핵심적인, 이를테면 가장 중요하고 위험 부담이 큰 코드를 먼저 검사하기
때문이다. 그와 달리 대부분의 테스트를 작성한 후에도 확인하지 않은 코드는 십중팔구 가장
사소하고 문제될 소지가 적은 부분이다.
테스트 작성에 쏟아 부은 노력
테스트의가치
마커스의 팀은 고지에 올라선 것이다. 고지란 [그림 1-1]에서 곡선의 평평한 윗부분을 말하는
데, 투자한 노력 대비 돌아오는 이익이 감소하는 구간이다. 개인적으로 자바 사용자그룹에서
만난 많은 팀이 이와 같은 현상을 경험해보았다고 말했다.
마커스의 생각을 바꿔준 사람은 세바스찬이었다. 그는 이전에 마커스가 일하는 투자 은행에도
컨설팅해준 바 있는 경험 많은 소프트웨어 아키텍트였다. 세바스찬은 셀프서비스 팀에 합류한
직후 마커스를 비롯한 새내기 팀원의 멘토가 되어주었다. 그는 웹 애플리케이션 개발에 많이
쓰이는 프로그래밍 언어에도 능숙했지만, 마커스가 단위 테스트를 작성하는 방식에 특히 많은
영향을 주었다.
지금까지 마커스는 새 코드 작성 시 단위 테스트 작성까지 마친 후 버전 관리 시스템에 체크인
하는 습관을 길러왔다. 그런데 세바스찬의 방식은 좀 특이했다. 실패할 게 뻔한 테스트를 먼저
하나 만들고, 그 테스트가 성공할 만큼의 코드를 작성했다. 그리곤 다시 실패할 테스트를 또 하
32 Part I 기반 다지기
나 작성하는 식이다. 작업을 완료할 때까지 계속 이런 식이었다.
세바스찬과 함께하며 마커스는 자신의 프로그래밍 방식도 조금씩 개선됨을 느꼈다. 객체를 구
성하는 방식도 바뀌었고 완성된 코드도 어딘가 달라 보였다. 코드의 설계와 기능을 사용자의
시각에서 바라보기 시작한 까닭이다.
테스트는 실사용에 적합한 설계를 끌어내준다.
마커스는 마치 머릿속에서 전구가 ‘팍!’ 하고 켜진 것 같은 느낌이었다. 그는 달라진 프로그래밍
방식과 결과를 말로 표현하는 과정에서, 테스트가 단순한 품질 보증이나 실수 재발 방지 수단
만은 아님을 깨달았다. 테스트는 분명 코드를 설계하는 한 방식이기도 했다. 실패할 테스트를 거쳐
간 코드는 분명 필요한 기능을 모두 담고 있으면서도 이전 방식으로 작성한 코드보다 훨씬 간
결했다.
테스트는 원하는 동작을 명확히 알려주어 군더더기(gold-plating)를 없애준다.
이야기의 주인공인 마커스의 경험은 실제로 많은 테스트 추종 개발자가 테스트를 개발하며 깨
닫고 이해하는 과정을 그린 것이다. 처음에는 시간을 좀먹는 부끄러운 실수를 예방할 생각으로
자동화된 단위 테스트를 작성하기 시작한다. 그리고 시간이 지날수록 안전장치로써의 역할은
전체 그림의 일부일 뿐임을 깨닫게 된다. 오히려 테스트를 코딩에 접목하면서 경험하는 사고
과정이 더 가치 있을 것이다.
자동화된 단위 테스트는 개발자가 직접 작성해야 한다는 인식은 이미 널리 퍼져있지만, 어떤
테스트를 얼마나 많이 작성해야 하는가에 대한 인식은 여전히 부족하다. 개인적인 컨설팅 경험
에 비추어봐도 테스트의 필요성을 이해하지 못하는 프로그래머는 거의 없었다. 하지만 제품 코
드의 모든 경로를 훑고 있음을 의미하는 100% 코드 커버리지 달성을 주장하는 프로그래머는
거의 없었다.
여기서 얻을 수 있는 결론은 무엇일까? 테스트를 작성해야 한다는 데에는 누구나 동의하지만,
커버리지가 100%에 근접해질수록 테스트를 더 작성해야 하는가에 대해서는 확신이 줄어든다.
작성할 테스트를 거의 다 작성했다면 나머지 코드에서 문제가 발견될 가능성은 낮아지기 때문
이다. 이것이 바로 수확 체감diminishing return이라는 것으로 [그림 1-1]의 곡선이 잘 나타내주고
있다.
결국, 신중히 고민해서 만든 첫 100개의 테스트로는 개선 효과가 피부로 느껴지겠지만, 이미
33CHAPTER 1 좋은 테스트의 약속
30,000개나 갖춰진 상태에서는 100개를 더 만드는 것으로는 변화를 체감하기 어렵다. 하지만
마커스가 멘토를 통해 깨달은 것처럼 여기서 끝이 아니다. 우리 앞에는 아직 두 번째 고지가 남아
있다.
테스트를 작성해서 얻게 되는 가장 큰 수확은 테스트 자체가 아니다. 작성 과정에서 얻는 깨달음이다.
마커스 이야기에서는 테스트를 바라보는 두 가지 인식을 강조했다. 두 개의 고지란 바로 그 각각
의 인식을 기반으로 테스트를 작성했을 때 도달할 수 있는 최고 경지를 뜻한다. 물론 테스트의
잠재 가치를 모두 일깨우려면 [그림 1-2]의 고지 두 곳을 모두 점령해야 한다.
그림 1-2 처음 도달할 수 있는 낮은 고지에 이르면 테스트를 추가하고 개선해도 더 이상의 가
치를 끌어내기 어려워진다. 그 위의 두 번째 고지는 테스트가 단순한 검증 수단 이상임을 깨닫
는 사고의 전환을 통해야만 발견할 수 있는 더 높은 경지다.
테스트를 설계 수단으로
이용할 경우
테스트를 품질 보증
수단으로만 이용할 경우
테스트 작성에 들인 노력
테스트의가치
테스트를 품질 보증 수단으로만 인식하는 한 얻을 수 있는 잠재적 가치는 [그림 1-2]의 낮은
곡선을 벗어날 수 없다. 사고의 틀을 깨고 테스트를 프로그래밍 도구, 즉 설계 도구로 인식하는
순간 품질 고지를 뛰어넘어 설계 고지에 도달하는 길이 열리게 된다.
불행하게도 테스트로 설계한다는 인식 전환 단계를 통과하지 못한 개발자가 훨씬 많아서 대부분
의 제품 코드는 첫 번째 곡선 어딘가에 머물러 있다. 마찬가지로 개발자는 커지는 테스트 스위
트test suite 관리 비용에도 별로 관심을 두지 않는다. 이쯤에서 질문이 하나 떠오른다. 프로그래머
생산성에 영향을 주는 요소에는 무엇이 있고, 그 안에서 단위 테스트의 역할은 무엇일까?
34 Part I 기반 다지기
1.2.1 생산성에 영향을 주는 요소
테스트를 빠르게 작성하려면 무엇이 중요한가는 신경 쓰지 않고 열심히 타이핑만 하면 된다.
하지만 많은 사람들이 테스트를 작성하느라 시간을 쏟고, 중복을 없애고, 구조와 명료성은 물
론 유지보수에까지 신경을 쓰는 데는 그만한 이유가 있다.
테스트 코드는 제품 코드보다 간결한 게 보통이다.4
그렇다 해서 테스트 코드를 허투루 작성하
고 문제를 심어 놓으면, 나중에 분명 발목 잡힐 날이 올 거다. 중복도 많고 쓸데없이 복잡한 테
스트 코드는 생산성을 떨어뜨리고 테스트의 긍정적 효과마저 앗아간다는 걸 명심하자.
엉터리로 작성한 테스트 코드는 가독성만이 아니라 안정성과 신뢰성, 실행 속도에도 악영향을
준다. [그림 1-3]은 개발자 생산성에 영향을 주는 요소의 역학 구조를 테스트 관점에서 바라본
모습이다.
생산성에 직접 영향을 주는 피드백 주기와 디버깅 시간에 주목해보자. 경험상 이 두 가지가 가장
유력한 야근의 요정이다.5
실수하자마자 곧바로 알아차릴 수만 있다면 지루한 디버깅을 상당수
피할 수 있지만, 피드백 주기가 길어질수록 디버깅 시간도 길어지게 마련이다.
그림 1-3 테스트는 다방면에 걸쳐 생산성에 직간접적인 영향을 준다.
피드백 주기의
길이
개발자
생산성
디버깅
결함
테스트
신뢰성
테스트 결과의
정확성 테스트
안정성
단축시킨다.
감소시킨다.
피하게
한다.
예방한다.
예방한다.
유발한다.
향상시킨다.
향상시킨다.
감소시킨다.
테스트
실행 속도
테스트
가독성
4 저자주_ 예를 들어 조건문이나 반복문을 사용하는 테스트는 많지 않다.
5 저자주_ 생산성 저하의 끝판왕은 회의라고들 얘기하지만, 그에 관해서는 다른 책을 찾아보길 바란다.
35CHAPTER 1 좋은 테스트의 약속
버그 수정 비용의 증가
버그 수정 비용은 평균적으로 얼마나 될까? 런던에서 열린 ‘XP Day 2009 컨퍼런스’에서 마크 스트리에벡
(Mark Striebeck)은 구글에서 결함을 수정하기 위해 지연된 시간을 비용으로 계산해서 공개하였다.
구글이 측정한 바로는 프로그래머가 버그를 만들자마자 즉시 수정한다면 $5를 쓴 것이다. 같은 결함을 프로
젝트 전체 빌드 때 발견하면 비용은 $50가 된다. 만약 통합 테스트까지 살아남으면 $500로 증가하며 시스템
테스트에 이르면 $5,000까지 치솟는다.
이 수치만 봐도 문제는 가능한 한 빨리 발견해야 한다는 건 이론의 여지가 없다.
테스트 실행 속도는 변경사항을 검증하고 확인validation and verification하기 위해 기다리는 시간에 직결
된다. 이 역시 주요한 요소라 그림에서도 굵게 강조해 두었다. 나머지 주요 요소 세 개는 모두
프로그래머가 해야 할 디버깅의 양과 관련이 있다.
가독성이 떨어지면 자연스럽게 분석이 더뎌지고 디버거를 사용해야 할 상황까지 만들 수 있다.
테스트 코드를 읽어봐도 무슨 말인지 이해하기 어렵기 때문이다. 이처럼 가독성이 안 좋으면
실수한 곳을 찾기 어려워 더 많은 결함이 만들어지고, 늘어난 결함은 디버깅 시간 증가로 이어
진다.
테스트 결과의 정확성도 발견하지 못하고 놓치는 결함의 수에 많은 영향을 준다. 실수로 결함을
만들어도 테스트 스위트가 찾아줄 거라며 믿고 의지하고 싶다면 정확성이라도 반드시 보장되
어야 한다. 생산성에 영향을 주는 나머지 요인인 신뢰성trustworthiness과 안정성reliability이 바로 이 테
스트 정확성과 직접 연관되어 있다. 테스트 결과를 믿고 싶다면 테스트가 약속한 것을 확실히
잡아내고 몇 번을 수행해도 항시 같은 결과가 나오도록 만들어야 한다.
이상의 생산성 역학 구조를 잘 이해하면 여러분도 품질 고지에 올라설 수 있다. 바로 이 요소들
이 개발자 생산성을 올려주는 핵심이기 때문이다. 또한, 생산적인 개발자가 되려면 마땅히 필
요한 도구도 능숙하게 다룰 줄 알아야 한다. 프로그래밍 언어의 기초를 다 익혔다면 표준 API
도 둘러보자. 문제에 대해 충분히 파악했다면 그 근본 원인을 파헤쳐보자. 바로 가독성, 안정
성, 신뢰성, 그리고 테스트 속도 말이다.
이들 원인은 책의 나머지 대부분에서 풀고자 하는 숙제이기도 하다. 즉 읽기 쉽고, 신뢰가 가고,
안정된 테스트 코드를 식별하는 능력을 키워주고, 그러한 테스트 코드를 만들고 관리할 수 있
도록 해주겠다.
36 Part I 기반 다지기
본격적인 논의에 앞서 [그림 1-2]의 두 번째 곡선이 뜻하는 바를 생각해보자.
1.2.2 설계 잠재력 곡선
제품 코드의 가장 대표적인 시나리오와 구조상 가장 치명적인 부분을 먼저 검사했다고 치자.
테스트 품질도 상급이고 철저한 리팩토링으로 중복까지 말끔히 제거해서 가볍고 유지보수도
쉬워졌다. 이어서 나머지 주요 기능을 모두 검사하고 getter/setter 등의 사소한 기능만 남았
다. 테스트 커버리지가 높은 것은 당연하다. 이 상태에서 마지막 남은 사소한 테스트는 작성해
봤자 큰 가치가 없다. 이는 수확 체감에 다다랐다는 신호로, 단지 테스트만 작성해서 얻을 수 있
는 가치의 한계점에 도달한 것이다.
이곳이 바로 일반적인 방식으로 도달할 수 있는 최고점인 품질 고지다. 그 한계를 뛰어넘어 한 차
원 높은 생산성을 맛보고자 한다면 환골탈태를 거쳐야 한다. 즉, 지금까지 가지고 있던 테스트
에 관한 사고의 틀을 깨야만 한다. 완전히 색다른 테스트의 가치를 찾아내야 숨어 있는 잠재력
을 끌어낼 수 있다. 실수가 반복되는 것을 예방한다는, 방어적이고 검증 지향적인 가치가 아닌,
더 창조적이고 설계 지향적인 가치가 바로 그것이다.
요약하면, 테스트의 잠재 가치를 전부 끌어내고 두 고지를 모두 정복하려면 다음처럼 하면 된다.
1 테스트 코드도 제품 코드를 다루듯 하라. 믿고 의지할 수 있을 만큼 철저하게 리팩토링하고 높은 품질을 유지하라.
2 테스트를 제품 코드가 목적과 쓰임새에 적합한 구조가 되게끔 이끌어주는 설계 수단으로 활용하라.
프로그래머 대부분이 잘 지키지 못하는 쪽은 첫 번째다. 테스트를 작성하고 관리하고 실행하는
비용을 최소화하는 동시에 고품질의 테스트 코드를 작성하는 걸 힘들어한다. 다행히도 이는 본
책에서 집중해서 다룰 주제인 좋은 테스트 작성하기의 영역이다.
달리 말하면, 설계 수단으로써의 테스트 쪽에는 많은 지면을 할애하지 않겠다는 뜻이다.6
그래
도 전반적인 역학과 작동 원리는 이해할 수 있도록 1.3절을 준비했다. 그럼 한번 시작해보자.
6 저자주_ 필자가 저술한 『Test Driven』 (매닝, 2007)은 이 주제에 딱 맞는 책이다. 스티브 프리먼(Steve Freeman)과 넷 프라이스(Nat
Pryce)가 저술한 『Growing Object-Oriented Software, Guided by Tests』 (Addison-Wesley, 2009)를 참고해도 좋다.
37CHAPTER 1 좋은 테스트의 약속
1.3 설계 수단으로써의 테스트
프로그래머가 작성한 자동화된 테스트는 전통적으로 크게 두 가지 목적을 위한 품질보증 수단
이었다. 첫째는 코드를 작성하는 즉시 정확하게 구현했는지 검사하는 것이고, 둘째는 그 후에
코드베이스가 커져도 계속 잘 동작하는지 지속해서 확인하는 것이다. 설계하고, 설계대로 코딩
하고, 생각대로 잘 구현되었는지 확인하는 것으로, 테스트를 검증 수단으로 활용하는 전형적인
모습이다.
자동화된 테스트를 설계 수단으로 이용하기 시작하면 모든 것이 뒤바뀐다. 테스트를 코드 설계
용으로 사용하면 익숙했던 설계, 코딩, 테스트의 순서가 테스트, 코딩, 설계로 바뀐다. 잘못 읽은 게
아니다. 테스트가 코딩보다 선행되고 설계로 마무리된다. 마지막의 설계 단계는 리팩토링이라는
이름으로 더 유명하다. 결과적으로 [그림 1-4]와 같은 테스트 → 코딩 → 리팩토링의 순서가 된다.
그림 1-4 테스트 주도 개발 프로세스는 실패하는 테스트를 작성하는 것으로 시작하여, 테스트를
성공하게 만드는 코드를 작성하고, 작성된 코드의 설계를 개선하는 리팩토링으로 마무리된다.
테스트 코딩
(반복)
리팩토링
지금 하는 얘기가 친숙하게 느껴진다면 아마도 테스트 선행 프로그래밍이나 테스트 주도 개발에 대해
들어봐서일 것이다.7
마침 우리도 그 얘기를 하는 중이니 원래의 이름대로 부르기로 하자.
1.3.1 테스트 주도 개발
[그림 1-5]의 테스트 주도 개발TDD은 간단한 아이디어에서 시작된 프로그래밍 훈련법이다. ‘코
드가 갖춰야 할 기능을 명시하는, 실패하는 테스트 없이는 코드를 작성하지 않는다.’ 이것이 바
로 테스트 선행 프로그래밍이라 불리는 이유다.
7 저자주_ 혹은 몇 페이지 전에 읽은 마커스와 세바스찬 이야기 때문일 지도 모르겠다.
38 Part I 기반 다지기
그림 1-5 테스트 주도 개발에서는 실패하는 테스트 작성하기, 테스트 통과하기, 중복을 줄이고 의도를 명확하
게 하기 위한 코드 리팩토링을 반복한다. 그리고 도중에 문제가 생기지는 않았는지 확인하기 위해 매 단계 테스
트를 실행한다.
새로운 테스트를
작성한다.
모든 테스트를
실행한다.
모든 테스트를
실행한다.
리팩토링
이전으로
복원한다.
모든 테스트를
실행한다.
테스트 통과?
테스트 통과?
제품 코드와
테스트 코드를
리팩토링한다.
테스트 통과?
시작
예
아니요
예
예
아니요
아니요
테스트를
만족시키는
제품 코드
작성한다.
테스트를 먼저 작성하면 소위 테스트로 설계한 제품 코드가 만들어진다. 여기에는 다음과 같은
긍정적인 효과가 따라온다.
● ‘사용 가능한 코드가 만들어진다.’ 즉, 제품 코드의 설계와 API가 활용 시나리오에 적합한 모습으로 거듭난다.
● ‘코드가 가벼워진다.’ 실제로 활용할 시나리오에서 요구하는 기능만을 담게 된다.
첫째, 프로젝트 진척도나 필요한 다른 컴포넌트, 클래스, 인터페이스가 갖춰져 있는지와 상관
없이 여러분의 손에는 항시 명확한 사용 시나리오가 딸린 설계만이 쥐어져 있게 된다. 더구나,
그 시나리오는 자동화된 단위 테스트라는 구체적이고 실행 가능한 형태로 구현되어 있다. 그래
서 테스트에 실패한다는 것은 테스트가 통과하도록, 아니 딱 통과할 정도만 제품 코드를 손봐
주라는 명확한 목표가 되어준다.
실행할 수 있는 테스트 코드로 시나리오를 그려내는 일은 분명 설계 영역에 속한 활동이다. 테
스트 코드는 제품 코드를 사용하는 고객의 입장이 되어 코드 한 줄 쓰기도 전에 설계가 올바로
되었는지 검증해준다. 요구사항을 구체화한 이 예제는 아주 강력한 검증 도구로, 오직 테스트
를 설계 수단으로 활용할 때만 얻을 수 있는 이점이기도 하다.
39CHAPTER 1 좋은 테스트의 약속
둘째, 테스트를 통과할 만큼만 코딩한다는 규칙을 잘 따라주면 설계를 간결하면서도 목적에 딱
맞도록 유지할 수 있다. 시나리오를 갖추지 못한 코드가 단 한 줄도 없으므로 버릴 게 하나도
없다. 반면 우발적 복잡성accidental complexity은 코드 품질을 떨어뜨리는 가장 악명 높은 적이자 개발
자 생산성을 갉아먹는 주 요인이다.
우발적 복잡성이란 쓸데없이 복잡한 것을 말한다. 다시 말해 요구조건은 그대로 만족하면서도
더 단순한 설계로 대체할 수 있다는 뜻이다. 프로그래머는 종종 자신도 이해하기 어려운 복잡
한 설계를 만들어서 자신이 얼마나 똑똑한지 보여주고 싶어한다. 여러분 내면에도 이와 같은
원초적 본능이 꿈틀대고 있을 것이다. 하지만 설계가 복잡해질수록 생산성이 떨어지는 건 당연
하므로, 불필요하게 복잡하게 만드는 건 정말 쓸데없고 비생산적이다.
결함이나 빠진 기능을 명시하는 테스트, 테스트를 통과할 만큼의 코드만 작성한다는 규칙, 그
리고 간결한 설계8
를 지향하는 철저한 리팩토링은 우발적 복잡성을 크게 줄여준다. 물론 만병
통치약이 될 순 없다. 최종 결과는 결국 프로그래머의 설계 감각과 경험에 크게 좌우되기 때문
이다.
TDD는 사실 책 몇 권은 거뜬히 써낼 수 있을 만큼 거대한 큰 주제다. 필자가 저술한 『Test
Driven』과 스티브 프리먼과 넷 프라이스가 최근에 쓴 『Growing Object-Oriented
Software, Guided by Tests』 등이 그 예다. 개인적으로는 제목부터 간결한 켄트 벡Kent Beck의
『Test Driven Development: By Example』9
를 추천한다.
TDD 관련 자료는 주변에서 쉽게 찾을 수 있으니 본 책에서는 여기까지만 이야기할 테니, 더
깊이 있는 설명이 필요한 독자는 직접 구해보길 바란다. 다만 TDD 관련 영역 중에서도 우리의
핵심 주제인 좋은 테스트와 밀접한 행위 주도 개발은 그냥 지나칠 수 없었다.
1.3.2 행위 주도 개발
행위 주도 개발BDD, Behavior-driven development이란 말을 들어봤는지 모르겠다. 사람들이 테스트 선
행 방식으로 프로그래밍하기 시작한 건 족히 수십 년은 되었지만, 우리가 알고 있는 테스트 주
8 저자주_ 간결한 설계(simple design)는 필요한 기능마저 수행하지 못할 만큼 지나치게 단순화한 설계(simplistic design)와는 전혀 다
른 개념이다.
9 저자주_ Addison-Wesley, 2002.
번역서 『테스트 주도 개발』 (김창준/강규영 역, 인사이트, 2005)
40 Part I 기반 다지기
도 개발은 1990년대에 와서야 이름이 생기고 체계를 갖추게 되었다.
약 10여 년이란 세월이 더 흘러, 댄 노스Dan North라는 런던의 컨설턴트는 차세대 테스트 선행 프
로그램을 주도하는 선두에 서게 된다. 그는 TDD에서 말하는 테스트라는 용어가 사람들을 잘못
된 길로 인도함을 깨달았다. 그래서 자신만의 TDD 방식을 만들고 행위 주도 개발이라는 이름
을 붙였다. 그는 2006년 『Better Software』에 기고한 글에서 행위 주도 개발을 다음과 같이
설명하였다.
문득 TDD에 대한 사람들의 오해 대부분은 테스트라는 단어 때문이라는 생각이 스쳤다.
테스트가 TDD의 본질이 아니라고 주장하는 게 아니다. 테스트 메서드가 코드의 동작을 보
장하는 효과적인 방법인 건 확실하다. 그런데 그 테스트가 시스템의 행위를 올바로 기술하
지 못한다면, 분명 잘못이 있는데도 개발자는 아무 문제 없다고 믿는 상황을 만든다.
나는 TDD에서 테스트가 들어가야 할 자리를 행위Behavior로 바꿔 사용하기 시작했다. 그러자
어휘적으로도 쏙 와 닿을 뿐 아니라 다른 사람을 가르치며 자주 받았던 질문들이 거짓말처
럼 해결되었다. 나는 이제 TDD와 관련된 질문 몇 가지의 해답을 알게 되었다. 테스트의 이
름을 짓는 건 정말 쉬워졌다. 검사하려는 행위를 기술하는 문장이면 된다. 테스트할 범위를
정하는 문제의 답도 간단하다. 답은 한 문장으로 기술할 수 있는 만큼의 행위다. 테스트가
실패하면 어떻게 해야 할까? 앞서 기술한 방식만 잘 따르면 된다. 새로운 버그가 만들어졌
건 행위가 바뀌었건 테스트가 더는 유효하지 않게 되었건 달라질 건 전혀 없다.
생각의 초점을 테스트에서 행위로 옮기는 것이 대단한 발견임을 깨달은 후부터 나는 TDD
를 BDD 혹은 행위 주도 개발이라 부르기 시작했다.
댄이 BDD라는 용어를 들고 와 전파하기 시작하자 전 세계 소프트웨어 개발 커뮤니티의 개발자
가 예제 주도example-driven, 행위명세 지향specification-of-behavior oriented 등 댄의 BDD를 구체화한 아
이디어를 발전시켜 나갔다. 나아가 요즘에는 코딩 외의 분야에서도 BDD라는 용어가 사용되
고 있다. 대표적으로는 요구 사항 단계의 비즈니스 분석과 명세화 시에 BDD를 사용한다.
BDD 실천자가 보장하는 특이한 개념으로 인수 테스트를 통한 ‘외부로부터의’ 개발이 있다. 『The
Cucumber Book: Behaviour-Driven Development for Testers and Developers』의
저자인 매트 윈Matt Wynne과 애슬랙 헬러조이Aslak Hellesøy의 설명을 들어보자.
행위 주도 개발은 최고의 TDD 실천자들의 좋은 습관을 정형화하여 만들어낸 TDD 기반
41CHAPTER 1 좋은 테스트의 약속
방법론이다. 최고의 TDD 실천자들은 외부로부터의 개발 방식을 사용한다. 즉, 그들이 가
장 먼저 작성하는, 실패하는 테스트는 시스템의 행위를 고객의 관점에서 서술한 인수 테스
트라고 할 수 있다. BDD 실천자로서 우리는 팀원 누구라도 쉽게 읽고 이해할 수 있도록 신
경 써서 인수 테스트를 작성한다. 이렇게 작성된 사용 예를 비즈니스 관계자에게 건네서 본
격적인 구현에 앞서 우리가 만들려는 방향이 올바른지 확인받는다.
이미 BDD 관련 도구와 프레임워크도 다수 만들어져 그 사상과 실천법과 규약 등을 소프트웨
어 개발 환경에 녹여내고 있는 모습을 보면 BDD가 발전하고 있는 것은 확실해 보인다. 그에
관해서는 8장에서 소개할 생각이다.
앞으로 좋은 테스트란 단어가 나올 때마다 댄의 깨달음을 상기하고 단어에 유념하기 바란다. 어
휘는 생각보다 중요하다.
1.4 요약
프로그래머가 마구잡이식 코딩에서 벗어난 지는 한참이 지났다. 개발자 테스트와 자동화된 테스
트는 이미 우리 일상으로 자리 잡았고, 표준화까지는 아니더라도 활발하게 논의 중인 주제임은
분명하다. 코드 전반을 보호해주는 자동화된 테스트 스위트의 가치를 더는 부정할 수 없다.
1장에서 여러분은 두 개의 고지가 무엇인지 배웠다. 이미 매우 높은 커버리지를 달성하여 테스
트를 더 만들어봐야 얻을 게 거의 없는 지점이 바로 첫 번째 고지다. 하지만 우리는 더 높이 오
를 수 있다. 테스트의 품질까지 신경 쓴다면 첫 번째 고지를 박차고 올라 더 위로 올라설 수 있
다. 전자가 테스트를 갖춰야 하는 이유라면 후자는 좋은 테스트를 갖춰야 하는 이유다. 이것이
여러분이 이 책을 산 이유고 2장 이후로 함께 도전할 과제다.
중도에서 포기하면 아무것도 얻을 게 없다. 함께 꼭 정상까지 올라가보자.
43
좋은 테스트란?
CHAPTER
2
이 장의 내용
● 무엇이 “좋은” 테스트를 만드는가?
● 테스트를 대하는 태도
● 신뢰할 수 있는 테스트의 중요성
44 Part I 기반 다지기
지금 우리는 좋은 테스트에 관해 배우려 한다. 좋은 테스트를 구분하고, 좋은 테스트를 직접 만
들 것이다. 또 그저 그런 테스트라도 좋은 테스트로, 최소한 그에 근접한 모습으로 개선하는 방
법을 배울 것이다. 그렇다면 무엇이 테스트를 좋게 만드는 것일까? 어떤 비결이 숨어 있을까?
다음과 같은 고려 사항이 있다.
● 테스트 코드의 가독성과 유지보수성
● 프로젝트 안에서, 그리고 소스 파일 안에서 코드는 적절히 구조화되어 있는가?
● 테스트가 무엇을 검사하는가?
● 테스트는 안정적이고 반복 가능한가?
● 테스트가 테스트 더블을 잘 활용하는가?
2장에서는 이 모두를 자세히 살펴볼 것이다.
아쉽게도 이 목록은 아직 완벽하지 않다. 테스트 품질에 영향을 주는 요소를 모두 나열하자면
끝도 없기 때문이다. 더구나 어떤 요소는 상황에 따라 별로 중요하지 않을 수도 있다. 예를 들
면 실행 속도가 중요한 테스트도 있는 반면 작은 기능 범위만 집중적으로 검증하는 것이 더 중
요한 테스트도 있다.
또한, 테스트 코드의 품질을 평가하는 기준도 사람마다 다르다. 코드가 좋다는 건 보통 개인 취
향에 좌우되고 나 또한 그런 개인 중 한 사람일 뿐이다. 그래서 이 책도 나의 편견과 편애에서
완전히 벗어날 수 없는 것이 현실이다. 개인 취향과는 거리를 두려고 노력했지만, 한쪽으로 치
좋은 테스트란?
CHAPTER 2
45CHAPTER 2 좋은 테스트란?
우친 부분이 있을지도 모르겠다. 그렇다고 이게 꼭 나쁘다고 생각하진 않는다. 결국, 내가 독
자에게 줄 수 있는 최선의 가치는 그동안 훌륭한 소프트웨어 전문가들과 함께하며 경험한 코드
(특히 테스트 코드)에 관한 나의 정직한 견해일 테니 말이다.
이러한 한계를 미리 밝혀두고, 이제 테스트 품질의 여러 측면을 이야기하면서 관심 가질 만한
주제를 찾아보자.
2.1 읽기 쉬운 코드가 유지보수도 쉽다
어제 컨설팅을 마치고 사무실로 돌아와, 곧 열릴 1K 경연대회에 참가하는 동료와 대화를 나눴
다. 데모파티에서는 꽤 역사와 전통이 있는 대회로, 컴퓨터와 침낭, 에너지 음료 등을 챙겨온
해커들이 넓은 공간에 모여 주말 내내 무언가를 시합하는, 일종의 괴짜들 잔치다. 역사적인 첫
대회 때부터 해커들은 온갖 정신 나간 기술을 구사해서 어설픈 3D 애니메이션을 만들어내곤
했다.
이런 대회에서는 보통 무엇인가의 크기를 제한한다. 내 동료가 준비 중인 대회 역시 1K라는 이
름이 말해주듯 컴파일된 실행파일의 크기가 최대 1K(1,024바이트)를 넘지 말아야 한다. 이
작은 공간에 의미 있는 프로그램을 욱여넣기 위해 참가자들은 동원 가능한 모든 꼼수를 고민해
야 한다. 코드를 꽉꽉 눌러 담을 때 자주 쓰이는 꼼수 중 하나로, 서로 다른 여러 변수에 똑같은
이름을 쓰는 방법이 있다. 결과코드의 압축률이 살짝 더 높기 때문인데, 한마디로 정상적인 코
딩 기술을 겨루는 대회는 아니다.
결과코드 역시 비정상인 건 마찬가지다. 1,024바이트 안에 마구잡이로 쑤셔 넣은 소스코드는
해독 불가능한 괴물이 된다. 어떤 프로그래밍 언어를 사용했는지조차 알아보기 어렵다. 말 그
대로 쓰기 전용 코드가 만들어진다고 할 수 있다. 압축하고 욱여넣는 작업이 한 번 시작되면 무
엇을 어디서 어떻게 수정해야 하는지 구분할 수 없게 된다. 즉, 더 이상의 기능 변경은 포기한
다는 의미다.
따끈따끈한 예를 보여주고자 최근 열린 JS1K 경연대회에 실제로 제출된 소스코드를 준비해보
았다.1
자바 스크립트를 사용하여 1,024바이트 이하로 제품을 만들어내는 대회다.
1 역자주_ 다른 작품이 궁금하다면 http://js1k.com에 방문해보기 바란다.
46 Part I 기반 다지기
<script>with(document.body.style){margin="0px";overflow="hidden";}
var w =window.innerWidth;var h =window.innerHeight;var ca =document.
getElementById("c");ca.width=w;ca.height=h;var c=ca.getContext("2d"); m=Math;fs=m.
sin;fc =m.cos;fm =m.max;setInterval(d,30);function p(x,y,z){ return{x:x,y:y,z:z};}
function s(a,z){r =w/10;R =w/3;b =-20*fc(a*5+t); return p(w/2+(R*fc(a)+r*fs(z+2*t))/
z+fc(a)*b,h/2+(R*fs(a))/z+fs(a)*b); }function q(a,da,z,dz){var v=[s(a,z),s(a+da,z),s(a+da,z
+dz),s(a,z+dz)]
;c.beginPath();c.moveTo(v[0].x,v[0].y);for(i in v)c.lineTo(v[i].x,v[i] .y);c.
fill();}var Z =-0.20;var t =0;function d(){t+ =1/30.0;c.fillStyle = "#000";c.
fillRect(0,0,w,h);c.fillStyle ="#f00";var n =30;var a =0;var da = 2*Math.PI/n;var
dz=0.25;for(var z=Z+8;z>Z;z-=dz){for(var i=0;i<n;i++){ fog=1/(fm((z+0.7)-3,1));if(z<=2)
{fog=fm(0,z/2*z/2);}var k=(205*(fog* Math.abs(fs(i/n*2*3.14+t))))>>0;k*=(0.55+0.45*fc((i/
n+0.25)*Math.PI*5) );k=k>>0;c.fillStyle="rgb("+k+","+k+","+k+")";q(a,da,z,dz);if(i%3= =0){ c.
fillStyle="#000";q(a,da/10,z,dz);}a+=da;}}Z-=0.05;if(Z<=dz)Z+=dz;} </script>
그렇다. 이는 너무 극단적인 예라 일반적인 소프트웨어 회사에서 경험할 법한 상황은 아니다.
그래도 이 정도까지는 아닐지라도, 현업에서도 머리를 쥐어뜯게 하는 코드는 모두 접해봤으리
라. 그런 부류의 코드를 보통 레거시legacy, 유산라 하는데, 다른 누군가로부터 물려받아 우리가 관
리해야 하기 때문이다. 너무 난해해서 이해해보려 할 때마다 머리를 혹사해야 한다는 점에서는
조금 다르지만 말이다. 이처럼 읽기 어려운 코드는 이해하는 데만 해도 너무 많은 에너지가 소
비되기 때문에 유지보수하기가 녹록하지 않다. 그뿐만 아니라 가독성과 결함 밀도는 반비례한
다는 연구 결과도 있다.2
즉, 읽기 어려운 코드일수록 결함 수가 많다.
자동화된 테스트는 결함을 효과적으로 막아주지만, 테스트 역시 코드인지라 가독성 문제에서
벗어날 수는 없다. 읽기 어려운 코드는 검증하기도 어렵고, 결과적으로 테스트를 조금만 작성
하는 사태로까지 이어진다. 또 그렇게 작성된 테스트는 우리가 생각하는 좋은 테스트와는 거리
가 멀다. 제품의 구조와 API가 테스트를 고려하지 않고 만들어졌다면 아무리 날고 기는 테스트
작성자가 와도 결국 끔찍한 구조의 이해하기 어려운 테스트밖에 만들 수 없기 때문이다.
코드 가독성이 코드 유지보수에 지대한 영향을 끼침을 확인했다. 그렇다면 테스트 코드는 가독
성 문제에서 자유로운가? 제품 코드와는 어떻게 다른가, 아니 과연 다르긴 할까? 우선 다듬어
지지 않은 난해한 테스트 코드를 하나 살펴보자.
2 저자주_ 레이몬드 버즈(Raymond Buse), 웨스틀리 와이머(Westley Weimer) 저. 『Learning a Metric for Code Readability』.
IEEE 소프트웨어 공학 분과, 2009년 11월 9일. IEEE 컴퓨터 학회 전자 도서관, http://doi.ieeecomputersociety.org/10.1109/
TSE.2009.70
47CHAPTER 2 좋은 테스트란?
코드 2-1 복잡하지는 않지만 가독성이 떨어지는 코드
@Test
public void flatten() throws Exception {
Env e = Env.getInstance();
Structure k = e.newStructure();
Structure v = e.newStructure();
//int n = 10;
int n = 10000;
for (int i = 0; i < n; ++i) {
k.append(e.newFixnum(i));
v.append(e.newFixnum(i));
}
Structure t = (Structure) k.zip(e.getCurrentContext(),
new IObject[] {v}, Block.NULL_BLOCK);
v = (Structure) t.flatten(e.getCurrentContext());
assertNotNull(v);
}
이 테스트는 무엇을 검사하려는 것일까? 여기서 무슨 일이 벌어지고 있는지 자신 있게 이야기
할 수 있는가? 여러분이 팀의 새내기라면 이 테스트의 의도로 파악하는 데 얼마나 걸릴 것 같
은가? 만일 어느 날 갑자기 테스트가 실패하기 시작한다면 어떤 수단을 동원할 텐가? 개인적인
느낌으로는 이 코드를 살펴본 사람은 누구나 여러 가지를 뜯어고치고 싶어할 것 같다. 그리고
그러한 개선의 공통 주제는 바로 가독성일 것이다.
2.2 구조화가 잘 되어 있다면 이해하기 쉽다
영광스럽게도 소스 파일 간에 매끄럽게 이어지지 못하는 코드를 접할 기회가 여러 번 있었다.
다른 파일을 전혀 참조하지 않는 경우도 있었다. 호출되는 코드까지 소스 파일에 하나에 전부
들어 있었던 까닭이다. 소스 파일이 너무 커져서 텍스트 편집기가 감당하지 못하고 죽어버린
적도 있다. 한 번은 웹 애플리케이션이 계속 에러를 내뱉기에 원인을 살펴봤다. 자바 서버 페이
지JSP, JavaServer Pages 파일이 너무 비대해져서 컴파일된 바이트 코드의 크기가 자바 클래스파일 명
세의 허용 범위를 넘어섰다. 어이없는 경험이었다. 구조화해두면 좋다는 점뿐 아니라 제대로
구조화하지 않으면 역으로 피해를 본다는 사실도 기억해둘 필요가 있겠다.
48 Part I 기반 다지기
이처럼 끝나지 않는 소스는 누구도 손대고 싶어하지 않았다. 가장 간단한 개념을 수정할 때조
차 어디부터 손대야 할지 찾기 어려웠다. 기댈 수 있는 구조가 전혀 없었기 때문이다. 분할정복
divide and conquer마저 불가능하여 코드 전부를 머릿속에 집어넣고 씨름하는 것 외에 다른 도리가
없었다.
[그림 2-1]에서와 같이 아무 구조나 다 코드를 이해하는 데 도움이 되는 건 아니다. 이해할 수
있는 구조가 필요한 것이다. 즉, 우리 두뇌와 사고 모델이 지지고 볶을 수 있을 정도로 정리된
구조라야 한다. 깊은 생각 없이 코드를 여러 소스 파일, 클래스, 메서드로 흩어버려도 한 번에
들여다봐야 할 코드의 양이 줄어드는 건 사실이다. 단, 당면한 주제인 프로그램 로직을 분해하
고 이해하는 데는 별다른 도움이 되지 못한다. 그래서 제대로 된 구조가 필요하다는 것이다.
그림 2-1 구조화되어 있느냐 아니냐의 단순한 문제가 아니다. 쓸모있는 구조라야 한다.
코드가 구조화
되어 있지 않다.
변경된 개념을 코드에
투영하기 어렵다.
사소한 변경이라도
악전고투를 유발한다.
아무도 손대려
하지 않는다.
코드가 좀 더
구조화된다. 하지만 우리는 손을
대야만 한다.작은 조각으로
나눈다.
하지만 쓸모있는 구조인가?
끝나지 않는 통짜 소스와 마주쳤을 때의 가장 확실한 대처법은 작은 조각으로 나누고 코드 뭉
텅이를 메서드로 뽑아내는 것이다. 500줄짜리 통짜 메서드라면 클래스 10개에 메서드 수십 개
정도로 재편할 수 있을 거다. 그렇다면 각 메서드는 평균 10줄 미만이 된다. 최소한 컴파일러
관점에서는 더 구조화된 게 확실하다. 또한, 화면을 스크롤하지 않고도 메서드 목록 전체를 살
펴볼 수 있게 된다.
하지만 코드가 도메인 모델이나 머릿속의 개념과 맞지 않아서 나눌 수 있는 명확한 경계를 찾을
수 없다면, 차라리 나누지 않느니만 못할 수도 있다. 하나의 개념이 여러 개의 물리적인 조각으
로 나뉜 꼴이 되어 여러 소스 파일을 이리저리 오가느라 시간만 더 낭비되기 때문이다. 사실은
간단한 문제다. 고수준 개념을 구현된 코드에 빠르고 정확하게 대입할 수 있는 구조면 된다.
테스트 코드는 여기에 딱 들어맞는 예다. 애플리케이션 전체를 자동화된 테스트 한 개로 보호하
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기
『Effective Unit Testing』 - 맛보기

More Related Content

What's hot

『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법
『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법
『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법
복연 이
 
플리토 코드리뷰 - Code Review in Flitto
플리토 코드리뷰 - Code Review in Flitto플리토 코드리뷰 - Code Review in Flitto
플리토 코드리뷰 - Code Review in Flitto
Yongjun Kim
 
2018 01-code review
2018 01-code review2018 01-code review
2018 01-code review
Myeongseok Baek
 
개발을잘하고싶어요-네이버랩스 송기선님
개발을잘하고싶어요-네이버랩스 송기선님개발을잘하고싶어요-네이버랩스 송기선님
개발을잘하고싶어요-네이버랩스 송기선님
NAVER D2
 
Java 그쪽 동네는
Java 그쪽 동네는Java 그쪽 동네는
Java 그쪽 동네는
도형 임
 
[NDC13] 70명이 커밋하는 라이브 개발하기 (해외 진출 라이브 프로젝트의 개발 관리) - 송창규
[NDC13] 70명이 커밋하는 라이브 개발하기 (해외 진출 라이브 프로젝트의 개발 관리) - 송창규[NDC13] 70명이 커밋하는 라이브 개발하기 (해외 진출 라이브 프로젝트의 개발 관리) - 송창규
[NDC13] 70명이 커밋하는 라이브 개발하기 (해외 진출 라이브 프로젝트의 개발 관리) - 송창규
ChangKyu Song
 
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
devCAT Studio, NEXON
 
파이썬 TDD 101
파이썬 TDD 101파이썬 TDD 101
파이썬 TDD 101
정주 김
 
코드 리뷰 시스템 소개
코드 리뷰 시스템 소개코드 리뷰 시스템 소개
코드 리뷰 시스템 소개Young-Ho Cha
 
[135] 우리 팀에서도 코드리뷰를 할 수 있을까 안오균
[135] 우리 팀에서도 코드리뷰를 할 수 있을까 안오균[135] 우리 팀에서도 코드리뷰를 할 수 있을까 안오균
[135] 우리 팀에서도 코드리뷰를 할 수 있을까 안오균
NAVER D2
 
xUnitTestPattern/chapter17
xUnitTestPattern/chapter17xUnitTestPattern/chapter17
xUnitTestPattern/chapter17Yoon Hee Hwang
 
더 나은 S/W를 만드는 것에 관하여 (OKKY 세미나)
더 나은 S/W를 만드는 것에 관하여 (OKKY 세미나)더 나은 S/W를 만드는 것에 관하여 (OKKY 세미나)
더 나은 S/W를 만드는 것에 관하여 (OKKY 세미나)
Jeongho Shin
 
『DirectX 12를 이용한 3D 게임 프로그래밍 입문』 - 맛보기
『DirectX 12를 이용한 3D 게임 프로그래밍 입문』 - 맛보기『DirectX 12를 이용한 3D 게임 프로그래밍 입문』 - 맛보기
『DirectX 12를 이용한 3D 게임 프로그래밍 입문』 - 맛보기
복연 이
 
유지보수를 고려한 SW 개발
유지보수를 고려한 SW 개발유지보수를 고려한 SW 개발
유지보수를 고려한 SW 개발
도형 임
 
2019 11-code review
2019 11-code review2019 11-code review
2019 11-code review
Myeongseok Baek
 
2022 01-okky-코드리뷰
2022 01-okky-코드리뷰2022 01-okky-코드리뷰
2022 01-okky-코드리뷰
Myeongseok Baek
 
도도와 파이썬: 좋은 선택과 나쁜 선택
도도와 파이썬: 좋은 선택과 나쁜 선택도도와 파이썬: 좋은 선택과 나쁜 선택
도도와 파이썬: 좋은 선택과 나쁜 선택
Jc Kim
 
짝 테스트(Pair Testing) 소개와 사례
짝 테스트(Pair Testing) 소개와 사례짝 테스트(Pair Testing) 소개와 사례
짝 테스트(Pair Testing) 소개와 사례
SangIn Choung
 
C++ 코드 품질 관리 비법
C++ 코드 품질 관리 비법C++ 코드 품질 관리 비법
C++ 코드 품질 관리 비법
선협 이
 

What's hot (20)

『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법
『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법
『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법
 
플리토 코드리뷰 - Code Review in Flitto
플리토 코드리뷰 - Code Review in Flitto플리토 코드리뷰 - Code Review in Flitto
플리토 코드리뷰 - Code Review in Flitto
 
2018 01-code review
2018 01-code review2018 01-code review
2018 01-code review
 
개발을잘하고싶어요-네이버랩스 송기선님
개발을잘하고싶어요-네이버랩스 송기선님개발을잘하고싶어요-네이버랩스 송기선님
개발을잘하고싶어요-네이버랩스 송기선님
 
Java 그쪽 동네는
Java 그쪽 동네는Java 그쪽 동네는
Java 그쪽 동네는
 
[NDC13] 70명이 커밋하는 라이브 개발하기 (해외 진출 라이브 프로젝트의 개발 관리) - 송창규
[NDC13] 70명이 커밋하는 라이브 개발하기 (해외 진출 라이브 프로젝트의 개발 관리) - 송창규[NDC13] 70명이 커밋하는 라이브 개발하기 (해외 진출 라이브 프로젝트의 개발 관리) - 송창규
[NDC13] 70명이 커밋하는 라이브 개발하기 (해외 진출 라이브 프로젝트의 개발 관리) - 송창규
 
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
 
파이썬 TDD 101
파이썬 TDD 101파이썬 TDD 101
파이썬 TDD 101
 
코드 리뷰 시스템 소개
코드 리뷰 시스템 소개코드 리뷰 시스템 소개
코드 리뷰 시스템 소개
 
[135] 우리 팀에서도 코드리뷰를 할 수 있을까 안오균
[135] 우리 팀에서도 코드리뷰를 할 수 있을까 안오균[135] 우리 팀에서도 코드리뷰를 할 수 있을까 안오균
[135] 우리 팀에서도 코드리뷰를 할 수 있을까 안오균
 
xUnitTestPattern/chapter17
xUnitTestPattern/chapter17xUnitTestPattern/chapter17
xUnitTestPattern/chapter17
 
더 나은 S/W를 만드는 것에 관하여 (OKKY 세미나)
더 나은 S/W를 만드는 것에 관하여 (OKKY 세미나)더 나은 S/W를 만드는 것에 관하여 (OKKY 세미나)
더 나은 S/W를 만드는 것에 관하여 (OKKY 세미나)
 
『DirectX 12를 이용한 3D 게임 프로그래밍 입문』 - 맛보기
『DirectX 12를 이용한 3D 게임 프로그래밍 입문』 - 맛보기『DirectX 12를 이용한 3D 게임 프로그래밍 입문』 - 맛보기
『DirectX 12를 이용한 3D 게임 프로그래밍 입문』 - 맛보기
 
유지보수를 고려한 SW 개발
유지보수를 고려한 SW 개발유지보수를 고려한 SW 개발
유지보수를 고려한 SW 개발
 
Prototyping
PrototypingPrototyping
Prototyping
 
2019 11-code review
2019 11-code review2019 11-code review
2019 11-code review
 
2022 01-okky-코드리뷰
2022 01-okky-코드리뷰2022 01-okky-코드리뷰
2022 01-okky-코드리뷰
 
도도와 파이썬: 좋은 선택과 나쁜 선택
도도와 파이썬: 좋은 선택과 나쁜 선택도도와 파이썬: 좋은 선택과 나쁜 선택
도도와 파이썬: 좋은 선택과 나쁜 선택
 
짝 테스트(Pair Testing) 소개와 사례
짝 테스트(Pair Testing) 소개와 사례짝 테스트(Pair Testing) 소개와 사례
짝 테스트(Pair Testing) 소개와 사례
 
C++ 코드 품질 관리 비법
C++ 코드 품질 관리 비법C++ 코드 품질 관리 비법
C++ 코드 품질 관리 비법
 

Viewers also liked

Chapter 1 0 이야기
Chapter 1 0 이야기Chapter 1 0 이야기
Chapter 1 0 이야기
ukjinkwoun
 
[NEXT] Nextgram Refactoring
[NEXT] Nextgram Refactoring[NEXT] Nextgram Refactoring
[NEXT] Nextgram Refactoring
YoungSu Son
 
개발 생산성 향상 기법 V1.2
개발 생산성 향상 기법 V1.2개발 생산성 향상 기법 V1.2
개발 생산성 향상 기법 V1.2
Daniel Lim
 
Legacy code refactoring video rental system
Legacy code refactoring   video rental systemLegacy code refactoring   video rental system
Legacy code refactoring video rental system
Jaehoon Oh
 
Head first chapter 1
Head first chapter 1Head first chapter 1
Head first chapter 1
ukjinkwoun
 
Spring batch example
Spring batch exampleSpring batch example
Spring batch example
Deepak Kumar
 
객체지향의 사실과 오해를 읽고
객체지향의 사실과 오해를 읽고객체지향의 사실과 오해를 읽고
객체지향의 사실과 오해를 읽고
Daniel Lim
 
Desing pattern study 8 template method pattern
Desing pattern study 8 template method patternDesing pattern study 8 template method pattern
Desing pattern study 8 template method pattern
dragor0123
 
Mongo jdbc
Mongo jdbcMongo jdbc
Mongo jdbc
Hyunho-Cho
 
Design patterns 스터디 -strategy패턴
Design patterns 스터디 -strategy패턴Design patterns 스터디 -strategy패턴
Design patterns 스터디 -strategy패턴
Hyunho-Cho
 
Clean code chapter1
Clean code chapter1Clean code chapter1
Clean code chapter1
ukjinkwoun
 
Tobi 스프링 2장 php version
Tobi 스프링 2장   php versionTobi 스프링 2장   php version
Tobi 스프링 2장 php version
ukjinkwoun
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
hyun soomyung
 
Learn design pattern-1
Learn design pattern-1Learn design pattern-1
Learn design pattern-1
Daniel Lim
 
Design pattern study 4 factory pattern _ by dragor0123
Design pattern study 4 factory pattern _ by dragor0123Design pattern study 4 factory pattern _ by dragor0123
Design pattern study 4 factory pattern _ by dragor0123
dragor0123
 
Desing Pattern-2
Desing Pattern-2Desing Pattern-2
Desing Pattern-2
Daniel Lim
 
Design pattern 4
Design pattern 4Design pattern 4
Design pattern 4
Daniel Lim
 
Game Design patterns, Visitor, State, FSM pattern
Game Design patterns, Visitor, State, FSM patternGame Design patterns, Visitor, State, FSM pattern
Game Design patterns, Visitor, State, FSM pattern
Young Ha Kim
 
소프트웨어 설계 악취: 기술 부채 관리 방법
소프트웨어 설계 악취: 기술 부채 관리 방법소프트웨어 설계 악취: 기술 부채 관리 방법
소프트웨어 설계 악취: 기술 부채 관리 방법
Jay Park
 
Refactoring tutorial
Refactoring tutorialRefactoring tutorial
Refactoring tutorial
Bingu Shim
 

Viewers also liked (20)

Chapter 1 0 이야기
Chapter 1 0 이야기Chapter 1 0 이야기
Chapter 1 0 이야기
 
[NEXT] Nextgram Refactoring
[NEXT] Nextgram Refactoring[NEXT] Nextgram Refactoring
[NEXT] Nextgram Refactoring
 
개발 생산성 향상 기법 V1.2
개발 생산성 향상 기법 V1.2개발 생산성 향상 기법 V1.2
개발 생산성 향상 기법 V1.2
 
Legacy code refactoring video rental system
Legacy code refactoring   video rental systemLegacy code refactoring   video rental system
Legacy code refactoring video rental system
 
Head first chapter 1
Head first chapter 1Head first chapter 1
Head first chapter 1
 
Spring batch example
Spring batch exampleSpring batch example
Spring batch example
 
객체지향의 사실과 오해를 읽고
객체지향의 사실과 오해를 읽고객체지향의 사실과 오해를 읽고
객체지향의 사실과 오해를 읽고
 
Desing pattern study 8 template method pattern
Desing pattern study 8 template method patternDesing pattern study 8 template method pattern
Desing pattern study 8 template method pattern
 
Mongo jdbc
Mongo jdbcMongo jdbc
Mongo jdbc
 
Design patterns 스터디 -strategy패턴
Design patterns 스터디 -strategy패턴Design patterns 스터디 -strategy패턴
Design patterns 스터디 -strategy패턴
 
Clean code chapter1
Clean code chapter1Clean code chapter1
Clean code chapter1
 
Tobi 스프링 2장 php version
Tobi 스프링 2장   php versionTobi 스프링 2장   php version
Tobi 스프링 2장 php version
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Learn design pattern-1
Learn design pattern-1Learn design pattern-1
Learn design pattern-1
 
Design pattern study 4 factory pattern _ by dragor0123
Design pattern study 4 factory pattern _ by dragor0123Design pattern study 4 factory pattern _ by dragor0123
Design pattern study 4 factory pattern _ by dragor0123
 
Desing Pattern-2
Desing Pattern-2Desing Pattern-2
Desing Pattern-2
 
Design pattern 4
Design pattern 4Design pattern 4
Design pattern 4
 
Game Design patterns, Visitor, State, FSM pattern
Game Design patterns, Visitor, State, FSM patternGame Design patterns, Visitor, State, FSM pattern
Game Design patterns, Visitor, State, FSM pattern
 
소프트웨어 설계 악취: 기술 부채 관리 방법
소프트웨어 설계 악취: 기술 부채 관리 방법소프트웨어 설계 악취: 기술 부채 관리 방법
소프트웨어 설계 악취: 기술 부채 관리 방법
 
Refactoring tutorial
Refactoring tutorialRefactoring tutorial
Refactoring tutorial
 

Similar to 『Effective Unit Testing』 - 맛보기

애자일 프랙티스
애자일 프랙티스애자일 프랙티스
애자일 프랙티스
한 경만
 
2011~2012 소프트웨어 관련도서 추천 리뷰 모음
2011~2012 소프트웨어 관련도서 추천 리뷰 모음2011~2012 소프트웨어 관련도서 추천 리뷰 모음
2011~2012 소프트웨어 관련도서 추천 리뷰 모음
Choulhyouc Lee
 
프로젝트 Xxx에 적용하고 싶은 개발방법
프로젝트 Xxx에 적용하고 싶은 개발방법프로젝트 Xxx에 적용하고 싶은 개발방법
프로젝트 Xxx에 적용하고 싶은 개발방법
도형 임
 
testing for agile?, agile for testing
testing for agile?, agile for testingtesting for agile?, agile for testing
testing for agile?, agile for testing
SangIn Choung
 
131 deview 2013 yobi-채수원
131 deview 2013 yobi-채수원131 deview 2013 yobi-채수원
131 deview 2013 yobi-채수원NAVER D2
 
[FEConf 2018] Front-End 프로젝트의 Test code 작성경험기
[FEConf 2018] Front-End 프로젝트의 Test code 작성경험기[FEConf 2018] Front-End 프로젝트의 Test code 작성경험기
[FEConf 2018] Front-End 프로젝트의 Test code 작성경험기
Ahreum Kim
 
테스트 냄새
테스트 냄새테스트 냄새
테스트 냄새
SukYun Yoon
 
행복한 개발을 위한_테스트_케이스
행복한 개발을 위한_테스트_케이스행복한 개발을 위한_테스트_케이스
행복한 개발을 위한_테스트_케이스
도형 임
 
[H3 2012] 행복한 개발을 위한 테스트 케이스
[H3 2012] 행복한 개발을 위한 테스트 케이스[H3 2012] 행복한 개발을 위한 테스트 케이스
[H3 2012] 행복한 개발을 위한 테스트 케이스
KTH, 케이티하이텔
 
사내 TDD 도입을 위한 설명 문서
사내 TDD 도입을 위한 설명 문서사내 TDD 도입을 위한 설명 문서
사내 TDD 도입을 위한 설명 문서
Kim kyoung-song
 
애자일과 애자일 테스트 소개 (테스트기본교육 3장 2절)
애자일과 애자일 테스트 소개 (테스트기본교육 3장 2절)애자일과 애자일 테스트 소개 (테스트기본교육 3장 2절)
애자일과 애자일 테스트 소개 (테스트기본교육 3장 2절)
SangIn Choung
 
D2 캠퍼스 세미나 - 학생 개발자에서 신입 개발자로 한단계 업그레이드 하기
D2 캠퍼스 세미나 - 학생 개발자에서 신입 개발자로 한단계 업그레이드 하기D2 캠퍼스 세미나 - 학생 개발자에서 신입 개발자로 한단계 업그레이드 하기
D2 캠퍼스 세미나 - 학생 개발자에서 신입 개발자로 한단계 업그레이드 하기
Soojin Ro
 
Agile sw development 101
Agile sw development 101Agile sw development 101
Agile sw development 101
Kiwon Kyung
 
발표자료 1인qa로살아남는6가지방법
발표자료 1인qa로살아남는6가지방법발표자료 1인qa로살아남는6가지방법
발표자료 1인qa로살아남는6가지방법
SangIn Choung
 
『클라우드 시스템을 관리하는 기술』 - 맛보기
『클라우드 시스템을 관리하는 기술』 - 맛보기『클라우드 시스템을 관리하는 기술』 - 맛보기
『클라우드 시스템을 관리하는 기술』 - 맛보기
복연 이
 
오픈 소스와 코드 리뷰
오픈 소스와 코드 리뷰오픈 소스와 코드 리뷰
오픈 소스와 코드 리뷰
Daniel Juyung Seo
 
SWDeveloperStory201501
SWDeveloperStory201501SWDeveloperStory201501
SWDeveloperStory201501Suho Kwon
 
오픈소스, 빡! 끝! - 제7회 삼성소프트웨어멤버십 기술전
오픈소스, 빡! 끝! - 제7회 삼성소프트웨어멤버십 기술전오픈소스, 빡! 끝! - 제7회 삼성소프트웨어멤버십 기술전
오픈소스, 빡! 끝! - 제7회 삼성소프트웨어멤버십 기술전
Daniel Juyung Seo
 

Similar to 『Effective Unit Testing』 - 맛보기 (20)

애자일 프랙티스
애자일 프랙티스애자일 프랙티스
애자일 프랙티스
 
2011~2012 소프트웨어 관련도서 추천 리뷰 모음
2011~2012 소프트웨어 관련도서 추천 리뷰 모음2011~2012 소프트웨어 관련도서 추천 리뷰 모음
2011~2012 소프트웨어 관련도서 추천 리뷰 모음
 
프로젝트 Xxx에 적용하고 싶은 개발방법
프로젝트 Xxx에 적용하고 싶은 개발방법프로젝트 Xxx에 적용하고 싶은 개발방법
프로젝트 Xxx에 적용하고 싶은 개발방법
 
testing for agile?, agile for testing
testing for agile?, agile for testingtesting for agile?, agile for testing
testing for agile?, agile for testing
 
131 deview 2013 yobi-채수원
131 deview 2013 yobi-채수원131 deview 2013 yobi-채수원
131 deview 2013 yobi-채수원
 
애자일프랙티스
애자일프랙티스애자일프랙티스
애자일프랙티스
 
[FEConf 2018] Front-End 프로젝트의 Test code 작성경험기
[FEConf 2018] Front-End 프로젝트의 Test code 작성경험기[FEConf 2018] Front-End 프로젝트의 Test code 작성경험기
[FEConf 2018] Front-End 프로젝트의 Test code 작성경험기
 
테스트 냄새
테스트 냄새테스트 냄새
테스트 냄새
 
행복한 개발을 위한_테스트_케이스
행복한 개발을 위한_테스트_케이스행복한 개발을 위한_테스트_케이스
행복한 개발을 위한_테스트_케이스
 
[H3 2012] 행복한 개발을 위한 테스트 케이스
[H3 2012] 행복한 개발을 위한 테스트 케이스[H3 2012] 행복한 개발을 위한 테스트 케이스
[H3 2012] 행복한 개발을 위한 테스트 케이스
 
사내 TDD 도입을 위한 설명 문서
사내 TDD 도입을 위한 설명 문서사내 TDD 도입을 위한 설명 문서
사내 TDD 도입을 위한 설명 문서
 
애자일과 애자일 테스트 소개 (테스트기본교육 3장 2절)
애자일과 애자일 테스트 소개 (테스트기본교육 3장 2절)애자일과 애자일 테스트 소개 (테스트기본교육 3장 2절)
애자일과 애자일 테스트 소개 (테스트기본교육 3장 2절)
 
D2 캠퍼스 세미나 - 학생 개발자에서 신입 개발자로 한단계 업그레이드 하기
D2 캠퍼스 세미나 - 학생 개발자에서 신입 개발자로 한단계 업그레이드 하기D2 캠퍼스 세미나 - 학생 개발자에서 신입 개발자로 한단계 업그레이드 하기
D2 캠퍼스 세미나 - 학생 개발자에서 신입 개발자로 한단계 업그레이드 하기
 
발표원고
발표원고발표원고
발표원고
 
Agile sw development 101
Agile sw development 101Agile sw development 101
Agile sw development 101
 
발표자료 1인qa로살아남는6가지방법
발표자료 1인qa로살아남는6가지방법발표자료 1인qa로살아남는6가지방법
발표자료 1인qa로살아남는6가지방법
 
『클라우드 시스템을 관리하는 기술』 - 맛보기
『클라우드 시스템을 관리하는 기술』 - 맛보기『클라우드 시스템을 관리하는 기술』 - 맛보기
『클라우드 시스템을 관리하는 기술』 - 맛보기
 
오픈 소스와 코드 리뷰
오픈 소스와 코드 리뷰오픈 소스와 코드 리뷰
오픈 소스와 코드 리뷰
 
SWDeveloperStory201501
SWDeveloperStory201501SWDeveloperStory201501
SWDeveloperStory201501
 
오픈소스, 빡! 끝! - 제7회 삼성소프트웨어멤버십 기술전
오픈소스, 빡! 끝! - 제7회 삼성소프트웨어멤버십 기술전오픈소스, 빡! 끝! - 제7회 삼성소프트웨어멤버십 기술전
오픈소스, 빡! 끝! - 제7회 삼성소프트웨어멤버십 기술전
 

More from 복연 이

​『9가지 사례로 익히는 고급 스파크 분석(2판) 』 맛보기
​『9가지 사례로 익히는 고급 스파크 분석(2판) 』 맛보기​『9가지 사례로 익히는 고급 스파크 분석(2판) 』 맛보기
​『9가지 사례로 익히는 고급 스파크 분석(2판) 』 맛보기
복연 이
 
​『골빈해커의 3분 딥러닝』 맛보기
​『골빈해커의 3분 딥러닝』 맛보기​『골빈해커의 3분 딥러닝』 맛보기
​『골빈해커의 3분 딥러닝』 맛보기
복연 이
 
​『함수형 반응형 프로그래밍』 맛보기
​『함수형 반응형 프로그래밍』 맛보기​『함수형 반응형 프로그래밍』 맛보기
​『함수형 반응형 프로그래밍』 맛보기
복연 이
 
『파이썬 라이브러리를 활용한 머신러닝』 맛보기
『파이썬 라이브러리를 활용한 머신러닝』 맛보기『파이썬 라이브러리를 활용한 머신러닝』 맛보기
『파이썬 라이브러리를 활용한 머신러닝』 맛보기
복연 이
 
『아마존 웹 서비스 인 액션』 맛보기
『아마존 웹 서비스 인 액션』 맛보기『아마존 웹 서비스 인 액션』 맛보기
『아마존 웹 서비스 인 액션』 맛보기
복연 이
 
『밑바닥부터 시작하는 딥러닝』 - 미리보기
『밑바닥부터 시작하는 딥러닝』 - 미리보기『밑바닥부터 시작하는 딥러닝』 - 미리보기
『밑바닥부터 시작하는 딥러닝』 - 미리보기
복연 이
 
『행복한 프로그래밍(개정판)』 - 맛보기
『행복한 프로그래밍(개정판)』 - 맛보기『행복한 프로그래밍(개정판)』 - 맛보기
『행복한 프로그래밍(개정판)』 - 맛보기
복연 이
 
『오픈스택 인 액션』 - 맛보기
『오픈스택 인 액션』 - 맛보기『오픈스택 인 액션』 - 맛보기
『오픈스택 인 액션』 - 맛보기
복연 이
 
『빠르게 훑어보는 구글 클라우드 플랫폼』 - 맛보기
『빠르게 훑어보는 구글 클라우드 플랫폼』 - 맛보기『빠르게 훑어보는 구글 클라우드 플랫폼』 - 맛보기
『빠르게 훑어보는 구글 클라우드 플랫폼』 - 맛보기
복연 이
 
『고성능 파이썬』 - 맛보기
『고성능 파이썬』 - 맛보기『고성능 파이썬』 - 맛보기
『고성능 파이썬』 - 맛보기
복연 이
 
『9가지 사례로 익히는 고급 스파크 분석』 - 맛보기
『9가지 사례로 익히는 고급 스파크 분석』 - 맛보기『9가지 사례로 익히는 고급 스파크 분석』 - 맛보기
『9가지 사례로 익히는 고급 스파크 분석』 - 맛보기
복연 이
 
『데이터 분석을 통한 네트워크 보안』 - 맛보기
『데이터 분석을 통한 네트워크 보안』 - 맛보기『데이터 분석을 통한 네트워크 보안』 - 맛보기
『데이터 분석을 통한 네트워크 보안』 - 맛보기
복연 이
 
『크리스 크로퍼드의 인터랙티브 스토리텔링』 맛보기
『크리스 크로퍼드의 인터랙티브 스토리텔링』 맛보기『크리스 크로퍼드의 인터랙티브 스토리텔링』 맛보기
『크리스 크로퍼드의 인터랙티브 스토리텔링』 맛보기
복연 이
 
『누워서 읽는 알고리즘』 - 미리보기
『누워서 읽는 알고리즘』 - 미리보기『누워서 읽는 알고리즘』 - 미리보기
『누워서 읽는 알고리즘』 - 미리보기
복연 이
 
『Modern PHP』 - 미리보기
『Modern PHP』 - 미리보기『Modern PHP』 - 미리보기
『Modern PHP』 - 미리보기
복연 이
 
『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 구성 지도
『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 구성 지도『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 구성 지도
『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 구성 지도
복연 이
 
『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 미리보기
『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 미리보기『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 미리보기
『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 미리보기
복연 이
 
어서 와! 번역은 처음이지?
어서 와! 번역은 처음이지?어서 와! 번역은 처음이지?
어서 와! 번역은 처음이지?
복연 이
 
『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기
『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기
『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기
복연 이
 
『게임 매니악스 액션 게임 알고리즘』 - 미리보기
『게임 매니악스 액션 게임 알고리즘』 - 미리보기『게임 매니악스 액션 게임 알고리즘』 - 미리보기
『게임 매니악스 액션 게임 알고리즘』 - 미리보기
복연 이
 

More from 복연 이 (20)

​『9가지 사례로 익히는 고급 스파크 분석(2판) 』 맛보기
​『9가지 사례로 익히는 고급 스파크 분석(2판) 』 맛보기​『9가지 사례로 익히는 고급 스파크 분석(2판) 』 맛보기
​『9가지 사례로 익히는 고급 스파크 분석(2판) 』 맛보기
 
​『골빈해커의 3분 딥러닝』 맛보기
​『골빈해커의 3분 딥러닝』 맛보기​『골빈해커의 3분 딥러닝』 맛보기
​『골빈해커의 3분 딥러닝』 맛보기
 
​『함수형 반응형 프로그래밍』 맛보기
​『함수형 반응형 프로그래밍』 맛보기​『함수형 반응형 프로그래밍』 맛보기
​『함수형 반응형 프로그래밍』 맛보기
 
『파이썬 라이브러리를 활용한 머신러닝』 맛보기
『파이썬 라이브러리를 활용한 머신러닝』 맛보기『파이썬 라이브러리를 활용한 머신러닝』 맛보기
『파이썬 라이브러리를 활용한 머신러닝』 맛보기
 
『아마존 웹 서비스 인 액션』 맛보기
『아마존 웹 서비스 인 액션』 맛보기『아마존 웹 서비스 인 액션』 맛보기
『아마존 웹 서비스 인 액션』 맛보기
 
『밑바닥부터 시작하는 딥러닝』 - 미리보기
『밑바닥부터 시작하는 딥러닝』 - 미리보기『밑바닥부터 시작하는 딥러닝』 - 미리보기
『밑바닥부터 시작하는 딥러닝』 - 미리보기
 
『행복한 프로그래밍(개정판)』 - 맛보기
『행복한 프로그래밍(개정판)』 - 맛보기『행복한 프로그래밍(개정판)』 - 맛보기
『행복한 프로그래밍(개정판)』 - 맛보기
 
『오픈스택 인 액션』 - 맛보기
『오픈스택 인 액션』 - 맛보기『오픈스택 인 액션』 - 맛보기
『오픈스택 인 액션』 - 맛보기
 
『빠르게 훑어보는 구글 클라우드 플랫폼』 - 맛보기
『빠르게 훑어보는 구글 클라우드 플랫폼』 - 맛보기『빠르게 훑어보는 구글 클라우드 플랫폼』 - 맛보기
『빠르게 훑어보는 구글 클라우드 플랫폼』 - 맛보기
 
『고성능 파이썬』 - 맛보기
『고성능 파이썬』 - 맛보기『고성능 파이썬』 - 맛보기
『고성능 파이썬』 - 맛보기
 
『9가지 사례로 익히는 고급 스파크 분석』 - 맛보기
『9가지 사례로 익히는 고급 스파크 분석』 - 맛보기『9가지 사례로 익히는 고급 스파크 분석』 - 맛보기
『9가지 사례로 익히는 고급 스파크 분석』 - 맛보기
 
『데이터 분석을 통한 네트워크 보안』 - 맛보기
『데이터 분석을 통한 네트워크 보안』 - 맛보기『데이터 분석을 통한 네트워크 보안』 - 맛보기
『데이터 분석을 통한 네트워크 보안』 - 맛보기
 
『크리스 크로퍼드의 인터랙티브 스토리텔링』 맛보기
『크리스 크로퍼드의 인터랙티브 스토리텔링』 맛보기『크리스 크로퍼드의 인터랙티브 스토리텔링』 맛보기
『크리스 크로퍼드의 인터랙티브 스토리텔링』 맛보기
 
『누워서 읽는 알고리즘』 - 미리보기
『누워서 읽는 알고리즘』 - 미리보기『누워서 읽는 알고리즘』 - 미리보기
『누워서 읽는 알고리즘』 - 미리보기
 
『Modern PHP』 - 미리보기
『Modern PHP』 - 미리보기『Modern PHP』 - 미리보기
『Modern PHP』 - 미리보기
 
『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 구성 지도
『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 구성 지도『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 구성 지도
『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 구성 지도
 
『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 미리보기
『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 미리보기『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 미리보기
『프로젝트 성패를 결정짓는 데이터 모델링 이야기』 - 미리보기
 
어서 와! 번역은 처음이지?
어서 와! 번역은 처음이지?어서 와! 번역은 처음이지?
어서 와! 번역은 처음이지?
 
『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기
『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기
『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기
 
『게임 매니악스 액션 게임 알고리즘』 - 미리보기
『게임 매니악스 액션 게임 알고리즘』 - 미리보기『게임 매니악스 액션 게임 알고리즘』 - 미리보기
『게임 매니악스 액션 게임 알고리즘』 - 미리보기
 

『Effective Unit Testing』 - 맛보기

  • 1.
  • 2. Effective Unit Testing : 개발자를 위한 단위 테스트 초판발행 2013년 11월 10일 지은이 라쎄 코스켈라 / 옮긴이 이복연 / 펴낸이 김태헌 펴낸곳 한빛미디어(주) / 주소 서울시 마포구 양화로 7길 83 한빛미디어(주) IT출판부 전화 02–325–5544 / 팩스 02–336–7124 등록 1999년 6월 24일 제10–1779호 / ISBN 978–89–6848–062–1 13000 책임편집 배용석 / 기획 박민아 / 편집 박민아 디자인 표지 강은영, 내지 강은영, 조판 김현미 영업 김형진, 김진불, 조유미 / 마케팅 박상용, 박주훈, 서은옥 이 책에 대한 의견이나 오탈자 및 잘못된 내용에 대한 수정 정보는 한빛미디어(주)의 홈페이지나 아래 이메일로 알려주십시오. 잘못된 책은 구입하신 서점에서 교환해 드립니다. 책값은 뒤표지에 표시되어 있습니다. 한빛미디어 홈페이지 www.hanb.co.kr / 이메일 ask@hanb.co.kr Effective Unit Testing: A Guide for Java Developers by Lasse Koskela Original English language edition published by Manning Publications. USA. Copyright 2013 by Manning Publications Co.. Korean–language edition copyright 2013 by Hanbit Media, Inc. All rights reserved. 이 책의 한국어판 저작권은 대니홍 에이전시를 통한 저작권사와의 독점 계약으로 한빛미디어㈜에 있습니다. 신저작권법에 의해 한국 내에서 보호를 받는 저작물이므로 무단전재와 복제를 금합니다. 지금 하지 않으면 할 수 없는 일이 있습니다. 책으로 펴내고 싶은 아이디어나 원고를 메일(writer@hanb.co.kr)로 보내주세요. 한빛미디어(주)는 여러분의 소중한 경험과 지식을 기다리고 있습니다.
  • 4. 4 라쎄 코스켈라는 Reaktor 소속의 코치, 트레이너, 컨설턴트, 프로그래머로서 고객이 성공적인 소프트웨어 제품을 만드는 데 이바지하고 있다. 그는 기업용 애플리케이션에서부터 미들웨어 제품까지 다양한 영역의 소프트웨어 프로젝트를 경험해왔다. 공인 스크럼 트레이너(Certified Scrum Trainer)이기도 한 그는 근래에는 고객팀의 생산성 을 개선하고 끊임없이 배워가는 문화를 길러주는 교육 프로그램을 제공하거나 직접 맨토링하 는 데 시간을 쏟고 있다. 또한, 리더와 관리자를 위한 컨설팅 외에도 소프트웨어 개발팀과 일하 며 프로그래밍하는 것 역시 좋아한다. 여가 시간에는 오픈 소스 프로젝트에 참여하거나 소프트웨어 개발 관련 저술 활동을 한다. 직접 블로그(http://lassekoskela.com/thoughts/)도 운영하며, 이번 『Effective Unit Testing』은 2007년에 출간한 『Test Driven』에 이은 두 번째 작품이다. 그는 핀란드 애자일 커 뮤니티의 선구자 중 한 명으로 국제 컨퍼런스의 발표자로도 자주 얼굴을 비추고 있다. 옮긴이 이복연 wegra.eut@gmail.com 『JUnit in Action: 단위 테스트의 모든 것』(인사이트, 2011)을 번역했다. 고려대학교 컴퓨터 학과를 졸업하고 삼성 소프트웨어 멤버십을 거쳐 삼성 소프트웨어 연구소에 입사했다. 그동안 미디어솔루션센터에서 바다 단말 플랫폼과 소셜허브 개발에 참여했으며, 현재는 클라우드 기 반 서버/인프라 관련 업무를 진행 중이다. 소프트웨어 아키텍처 설계, 애플리케이션 라이프사 이클 관리(ALM), 애자일 등의 분야에 관심이 많다. 지은이 소개 옮긴이 소개
  • 5. 5 제품설계가 요구사항에 달아 소스코드로 서로 사맛디 아니할쌔 이런 전차로 어린 개발자가 검증하고저 홇배 이셔도 마침내 제 뜨들 시러 펴디 몯홇 하니라. 내 이랄 윙하야 어엿비 너겨 새로 책 한 권을 번역하노니 사람마다 해여 수비니겨 날로 쑤메 뼌한키 하고져 할 따라미니라. 처음 이 책을 접했을 때 가장 먼저 눈길을 사로잡았던 것은 바로 『Effective Unit Testing』이 라는 책의 제목과 테스트 가능 설계testable design라는 7장의 제목이었다. 과연 Effective라는 이름을 내걸기에 부끄럽지 않은 책일까? Effective로 시작하는 책 대부분은 유행에 흔들리지 않고 비교적 오랫동안 가치를 인정받는 듬직함을 보여준다. 단순한 따라하기 나 기교 중심의 어떻게how가 아닌, 주제에 관한 깊은 이해와 오랜 경험으로부터 우러나온 왜why 를 다루기 때문이다. 왜를 이해한다는 것은 명확한 목적의식을 가지고 행동하게 되며, 변화하 는 환경에서도 흔들리지 않는 근본적인 기준에 따라 판단하고 응용할 수 있게 됨을 의미한다. 이러한 관점에서 이 책은 전혀 부족하지 않다고 판단되었고 번역 제안을 수락한 결정적인 이유 가 되었다. 개인적으로는 2006년경에 테스트 가능 설계 안티 패턴을 정리하려던 적이 있었다. 홀대받는 테스 트가 사실은 제품 설계와 생산성에 큰 영향을 주므로 개발 초기부터 이를 고려하면 전반적인 개발 과정이 훨씬 효율적이고 부드럽게 진행된다는 점을 알리고 싶었다. 당시만 해도 개척할 게 많은 분야였던 터라 잘 다듬어서 저널이나 학술지에 내볼 요량이었다. 하지만 컨설턴트도 아니고 테스트가 주업도 아닌지라 원하는 만큼의 적절한 예제를 모으는 데 한계가 있었고, 결 옮긴이의 말
  • 6. 6 국 어설픈 초안 수준에서 그만두고 말았다.1 이러한 개인적 경험 때문에 테스트 가능 설계란 주제는 큰 호기심과 아쉬운 감정을 동시에 불러일 으켰다. 그래서 이 책을 통해 내가 정리하던 것과 얼마나 유사한지, 혹은 더 발전했는지 확인해 보고 싶었다. 결국, 구성이나 내용 면에서는 많은 차이를 보였지만 큰 그림과 의도는 일맥상통 했다. 그래서 이렇게 다른 이의 결실에 편승해서라도 그때 하고자 했던 이야기를 세상에 들려 주고 싶다는 동기가 더해졌다. 좋은 설계임을 증명하려거든 자동화된 테스트를 만들어보라! 흔히 실력 좋다고 알려진 개발자 중 많은 수가 무척 복잡하여 어떻게 쓰는지 모르겠는 코드를 내놓거 나 겉은 깔끔하나 그 정도가 지나쳐서 내부 동작원리는 알기 어려운 코드를 만들어내곤 한다. 이런 코드 는 검증하기 어렵다는 치명적인 단점이 있다. 개발자 자신이 시연할 때에는 잘 돌겠지만 다른 모듈과 통합할 시점이 되면, 혹은 제품이 출시된 후 소비자에 의해 다양한 패턴으로 사용되면 서 뒤늦게 문제가 하나씩 터져 나오는 경우가 많다. 단기간에 가시적 결과를 보여줄 수는 있지 만 이렇게 발견된 문제는 개발한 당사자가 아니면 쉽게 손대지 못하니 골치 아픈 상황을 낳기 도 한다. 이들의 능력을 깎아내리려는 의도는 절대 아니다. 다만, 한 차원 높은 생산성과 안정 된 품질, 그리고 동료 개발자도 쉽게 이해하고 배울 수 있는 코드를 작성하는 쉬운 방법이 있으 나 잘 알지 못하는 듯하여 안타까울 뿐이다. 그들에게 필요한 것은 테스트에 대한 인식 전환이다. 테스트란 단순한 기능 검증 수단만이 아 닌 요구사항을 명시한 문장이요, 모듈과 API 설계 수단이며, 사용설명서이자, 최고의 인수인 계/유지보수 자료이기까지 하다. 특히 개발자의 설계역량 면에서 본다면, 디자인 패턴에만 의 지하기보다 테스트하기 쉬운 설계를 추구하는 쪽이 훨씬 탄탄한 기본기와 응용력을 길러줄 것 1 역자주_ http://wegra.org/blog/?page_id=514
  • 7. 7 이라고 감히 단언할 수 있다. 여러분이 이 책을 테스트 지침서가 아닌 설계 지침서로 받아들이고 잘 따라준다면 어느덧 진일보한 자신의 실력에 놀라게 될 것이다. 아무쪼록 독자 여러분께 재미나고 유익한 책이 되길 기원하며, 책 내용 중 혹 궁금한 것이 있거 든 wegra.eut@gmail.com으로 물어봐주시길 바란다. 여건이 허락하는 한 성심껏 답변하도 록 노력하겠다. 마지막으로 휴일까지 반납하며 이 책이 나오기까지 함께 고생해주신 한빛미디어 박민아님, 역 자를 믿고 번역을 맡겨주신 한동훈님, 그리고 이토록 훌륭한 지혜를 공유해준 원서의 저자 라 쎄 코스켈라에게 감사의 마음을 전한다.2 옮긴이_ 이복연 2 편집자주_ 더불어 이 책의 베타리딩에 참여해주신 한빛리더스 이정재님께 감사드립니다.
  • 8. 8 2009년 6월 10일 밤, 매닝Manning의 크리스티나 러들로프Christina Rudloff로부터 한 통의 메일을 받 았다. 그녀는 로이 오쉐로브Roy Osherove의 저서 『The Art of Unit Testing in .NET』1 을 자바Java 에 맞게 다시 써줄 만한 사람을 찾고 있었다. 기꺼이 내가 해주겠노라 답했다. 이건 꽤 오래전의 이야기로, 지금 여러분의 손에 들려 있는 이 책은 로이의 것과는 사뭇 다른 모습이 되었다. 설명을 해보자면 이렇다. 처음에는 .NET을 자바로 단순 변환하는 일로 시작했다. 달라진 플랫폼과 도구만 반영하고 독 자에게 꼭 필요한 부분만 다시 쓰면서 말이다. 1장을 마치고 2장을 마치고 3장까지 써내려 가 다가 문득 하나를 깨달았다. 문장 몇 개 정도가 아니라 한 장chapter 전체를 내가 새로 쓰고 있는 게 아닌가? 문체도 나와 맞지 않았다. 로이와는 다른 방식을 선호하거나 그의 설명에 동의하지 못할 때도 종종 있었다. 여러분에게 따로 꼭 하고 싶은 말이 있거나, 설명을 보충하거나, 기초 부터 확실히 다지고 넘어가고 싶다는 욕심이 강하게 생겨나기도 했다. 결국, 처음부터 새로 시작하기로 했다. 처음 의도했던, 자바 버전에 맞게 쓰는 일을 넘어선 시점이었다. 좋은 테스트를 작성하는 방법 과 주의 사항에 관한 심도 있는 통찰을 통해 자바 프로그래머의 테스트 능력을 키워주는 새롭 고 독특한 책으로 거듭난 것이다. 로이의 생각도 다양한 형태로 이 책에 스며있다. 예컨대 2부 를 구성하는 4, 5, 6장의 이름은 로이의 것을 고스란히 차용했고, 7장도 상당 부분은 로이의 책 『The Art of Unit Testing in.NET』의 관련 내용에 기초하여 썼다. 이 책은 자바 개발자를 위해 쓰였지만, 독자 범위를 인위적으로 제한하고 싶지는 않았다. 비록 2부의 예제 코드는 모두 자바지만, 내용 자체는 언어에 너무 국한되지 않게 하려 노력했다. 좋 은 테스트를 작성하는 방법은 언어와 무관하니 설령 여러분의 주 언어가 자바가 아니더라도 이 1 저자주_ 번역서 『.NET 예제로 배우는 단위 테스트』 (송인철/황인석 역, 인사이트, 2010) 지은이의 말
  • 9. 9 책의 내용을 진지하게 읽어보기를 진심으로 권한다. 같은 맥락에서, 이 책을 JUnit 또는 개인적으로 선호하는 특정 Mock 객체 라이브러리를 배우 기 위한 튜토리얼tutorial로 만들고 싶지 않았다. 시시때때로 변하는 기술, 또는 출판 후 몇 달이 면 폐기될 지식은 배제하고, 나 자신이 정말 읽고 싶은 책을 쓰고 싶었다. 눈 감고도 사용할 만 큼 이미 익숙해져 버린 테스트 프레임워크나 쓰지도 않는 Mock 객체 라이브러리를 억지로 들 이대지 않는 그런 책 말이다. 그래서 특정 기술에 종속된 조언은 최대한 자제하였다. 물론 전혀 없다고 말할 순 없지만, 최선을 다했음을 알아줬으면 한다. 테스트 작성과 실행, 유지보수, 개 선에 빠져서는 안 될 기본적인 개념과 의미 있는 논의가 필요한 정도만을 담아내었다. 다시 한번 말하지만, 나 자신이 읽고 싶은 책을 쓰려고 노력했다. 여러분도 함께 즐겨주길 바라 고, 무엇보다 책 내용 중 일부라도 실천하는 독자가 나와준다면 더 바랄 것이 없다. 지은이_ 라쎄 코스켈라
  • 10. 10 대상 독자 이 책은 개발 경험의 많고 적음을 떠나 단위 테스트의 품질을 높이고자 하는 모든 자바 프로그 래머를 위해 쓰였다. 부록에 JUnit 테스트 프레임워크 사용법을 넣긴 했지만, 책의 주목적은 이미 테스트 프레임워크를 하나쯤 사용할 줄 아는 자바 프로그래머가 더 좋은 테스트를 만들도 록 이끌어주는 것이다. 여러분이 지금껏 작성한 테스트가 아무리 많더라도, 더 발전할 가능성 은 아직 남아 있다고 확신한다. 더불어 이 책은 그동안 명확하게 정립되지 못한 채 여러분 머릿 속에만 떠돌던 많은 생각을 자극해줄 것이다. 로드맵 『Effective Unit Testing』은 하나로 아울러 다루기에는 적합하지 않은 다각적인 문제를 다루 고 있다. 그래서 여러 차례 실패를 거듭한 끝에 책을 크게 세 부분으로 나눠 구성하는 것이 가 장 좋겠다는 결론을 얻었다. 긴 여정의 시작을 알리는 1부는 우리가 이루고자 하는 목적과 이를 프로젝트 초기부터 고려해 야 하는 이유를 알려준다. 좋은 테스트를 작성하기 위해 꼭 필요한 도구와 간단한 지침을 포함 하여 총 세 개의 장으로 구성했다. 1장에서는 자동화된 단위 테스트의 가치를 역설한다. 프로그래머 생산성에 영향을 주는 여러 요소를 생각해보고, 잘 작성된 자동화된 테스트가 생산성에 어떻게 이바지하는지 혹은 기운 빠 지는 일을 예방해주는지를 설명한다. 2장에서는 좋은 테스트의 조건을 정의한다. 여기에서 살펴볼 속성은 2부에서 본격적으로 다룰 테스트의 가독성, 유지보수성, 신뢰성을 이해하기 위한 기초 개념이다. 잠시 숨도 돌릴 겸, 3장에서는 좋은 테스트를 작성하기 위한 필수 도구인 테스트 더블을 소개 한다. 테스트 더블을 그저 사용할 줄 아는 것보다는, 주의해서 올바르게 활용할 줄 아는 것이 목표다. 테스트 더블이 만병통치약은 아니기 때문이다. 이 책에 대하여
  • 11. 11 2부에서는 주의해야 할 테스트 냄새1 를 쭉 나열한다. 테스트 작성 시 경계해야 할 패턴을 설명 하고, 그런 낌새를 느꼈을 때 적용할 수 있는 해결책을 제시할 것이다. 세부 주제는 크게 3개 다. 가독성을 떨어뜨리는 냄새, 잠재적으로 유지보수 악몽을 일으키는 냄새, 마지막은 신뢰성 을 떨어뜨리는 냄새다. 사실 여기서 다루는 냄새 중 상당수는 세 범주 어디에나 속할 수 있지 만, 그중 가장 두드러지는 효과가 무엇이냐를 기준으로 배치했다. 4장에서는 테스트 의도나 구현을 모호하게 하는 냄새를 집중적으로 공략한다. 테스트 코드 속 의 판독하기 어려운 단언문, 적절치 못한 추상화, 흩어진 정보 등을 다루게 된다. 5장에서는 끊임없는 야근을 강요하는 테스트 냄새를 살펴본다. 엉망으로 작성한 단위 테스트 는 조금만 손보려 해도 끝도 없는 수정을 유발하기도 하고, 사소한 수정 하나가 수백 개의 다른 테스트까지 고쳐야 하는 상황을 초래하기도 한다. 그리하여 테스트에서의 코드 중복, 조건부 로직, 그리고 파일시스템을 건드렸을 때의 악몽을 자세히 설명한다. 테스트 속도를 느려지게 하는 냄새도 여기 포함된다. 시간은 돈이다. 테스트 냄새의 마지막인 6장에서는 잘못된 가정 때문에 고생했던 경험으로부터 깨달은 지혜를 공유한다. 테스트 코드에 잘못 쓰인 주석 때문에, 혹은 우리 자신의 의도를 분명하게 표현하지 못해서 생겨난 가정을 살펴볼 것이다. 3부의 제목은 자칫 고급 주제가 될 뻔했다. 하지만, 1부와 2부의 내용을 숙지하지 않았더라도 자 바 개발자가 테스트를 작성하며 언제든 살펴볼 수 있는 주제다. 결국 좋은 단위 테스트를 만드 는 조건은 거의 예외 없이 우리가 처한 상황에 따라 달라진다. 그래서 어떤 프로그래머에게 아 주 시급한 주제가 다른 이에게는 하찮은 문제라 해도 전혀 놀랄 일이 아니다. 테스트 클래스의 상속 관계나 테스트 작성에 쓰인 프로그래밍 언어 혹은 빌드 인프라가 테스트를 실행하는 방식 에 기인한 문제 등 그 어떤 것도 예외는 아니다. 1 역자주_ 테스트 냄새란 테스트 코드에서 주로 나타나는 코드 냄새다. 즉 테스트를 이해하고 관리하기가 어렵다거나 결과의 정확성이 떨어 지는 등 개선의 여지가 있을 수 있다는 징후다.
  • 12. 12 7장에서는 2장에서 미처 다루지 못했던 테스트 가능 설계를 만드는 요소로 꾸며보았다. 유용한 원칙 몇 개와 우리가 생각하는 이상적인 모듈화 설계에 관해서 간략히 훑고, 테스트 불가 설계 라는 기본적인 테스트 가능성 문제를 공부한다. 마지막으로는 테스트 가능 설계로 이끌어줄 간 단한 지침을 준비해두었다. 8장에서는 ‘단위 테스트를 자바가 아닌 언어로 작성하고 싶다면?’이라는 질문으로 시작한다. 오늘날의 자바 가상 머신에서는 자바 외에도 수많은 언어를 사용할 수 있고 순수 자바 코드와 연동하는 것도 가능하다. 9장에서는 서서히 느려지는 빌드 속도와 그와 함께 늦어지는 피드백 주기라는, 현실에서 흔하 게 겪는 상황을 고민해본다. 테스트 코드와 인프라, 즉 안팎 모두에서 돌파구를 찾아보았다. 코 드 측면에서는 실행 속도를 개선하는 방법을, 인프라 측면에서는 더 빠른 하드웨어를 도입하는 것, 혹은 기존 하드웨어를 그대로 두고 작업 할당 방식을 바꿔보는 방법 등을 살펴본다. JUnit의 독보적인 명성과 업계 표준 단위 테스트 프레임워크라는 위치에도 불구하고, 모든 자 바 프로그래머가 이에 익숙한 것은 아니다. 그래서 JUnit의 진보된 기능을 충분히 활용하지 못 했던 독자를 위해 부록 두 개를 수록해뒀다. 부록 A에서는 JUnit을 이용하여 테스트를 작성하고 실행하는 방법을 간단히 설명한다. 이 부록 을 읽고 나면 JUnit API를 활용해서 테스트를 만들고 단언문을 쓰기가 한층 수월해질 것이다. 부록 B는 JUnit의 기능을 확장할 때 필요한 API라는 다소 깊이 있는 주제를 다룬다. JUnit의 상세 내용을 전부 다루겠다는 욕심은 없고, 단지 확장 시에 가장 일반적으로 쓰이는 두 가지 방 법인 규칙rule과 러너runner를 소개하고, 기본 규칙 몇 개를 선보이는 선에서 마무리하려 한다. 이 규칙은 그 자체로도 물론 유용하지만, 사용자 확장을 통해 어떤 일까지 더 할 수 있을지 감을 잡아줄 것이다. 코드 작성 규칙 및 소스코드 내려받기 이 책에 등장하는 코드 예제에는 자바 소스코드, 마크업 언어, 출력 리스트가 있다. 길이가 길
  • 13. 13 어지면 이름(헤더)을 붙여 별도의 코드로 제공하고, 짧은 코드는 본문 안에 그대로 두었다. 모 든 예제는 고정폭 글꼴로 표기하여 본문과 구분했다. 긴 코드에서는 본문에서 참조하기 좋도록 번호 붙은 주석을 사용하기도 한다. 소스코드는 www.hanb.co.kr/exam/2062에서 내려받을 수 있다. 책에서 선별한 소스코드 만 담아 놨으니, 여러분이 그 이상으로 발전시켜보기 바란다. 예제 코드는 자바 6로 작성했으니 호환 버전을 설치하기 바란다. 필요한 자바 환경은 www. oracle.com에서 받을 수 있다. 컴파일까지 해보려면 JRE가 아닌 JDK를 설치하는 걸 잊지 말자. 선호하는 IDE도 설치해두면 편하다. 최신 버전의 이클립스2 나 IntelliJ 아이디어(IDEA, www.jetbrains.com), 넷빈즈3 중 가장 마음에 드는 것을 설치하자. 여러분 손에 익은 도구 라면 무엇을 선택하건 상관없다. 책을 다 읽은 후엔? 이 책에서 얻은 통찰로 여러분의 단위 테스트는 눈에 띄게 향상될 것이다. 물론 긴 여정이 될 것이고 우리가 예측하지 못했거나 완벽히 답하지 못한 질문이 한두 개 나올 수 있다. 다행히도 그 여정에는 수많은 친구가 함께할 것이고, 그중 많은 이들이 테스트 코드의 미묘한 차이를 주 제로 기꺼이 토론하고 공유할 것이다. 매닝에서는 매닝의 저자와 이야기할 수 있는 온라인 포럼을 마련해두고 있다. 이 책도 마찬 가지다. www.manning.com/EffectiveUnitTesting에 열어둔 저자 온라인 포럼을 방문해 보자. Yahoo! Groups의 testdrivendevelopment와 extremeprogramming은 테스트 추종 프로 2 저자주_ Eclipse, www.eclipse.org 3 저자주_ NetBeans, www.netbeans.org
  • 14. 14 그래머 간의 논의가 끊이지 않는 포럼이다. 단위 테스트만 다루는 포럼은 아니지만, 관련 주제 를 논하기에 훌륭한 장소다. 테스트 코드 외적인 새로운 생각도 접할 좋은 기회가 될 것이다. 개발자 테스트에 더 충실한 포럼을 찾는다면 http://www.coderanch.com의 CodeRanch 를 방문해서 Testing 포럼을 찾아보라. 이곳에서도 좋을 사람을 많이 사귈 수 있을 것이다. 하지만, 여러분이 짠 테스트 코드를 놓고 옆의 동료와 적극적으로 토론해보는 것이 그 무엇보 다도 더 효율적인 실천법임을 말해두고 싶다. 개인적으로도 옆에서 함께 고민하던 동료가 나의 코드에 대한 최고의 통찰을 일깨워준 경우가 많다.
  • 15. 15 『Effective Unit Testing』 표지 그림의 제목은 크로아티아 달마티아 드리니스에서 온 사내A Man from Drnis, Dalmatia, Croatia다. 이 그림은 니콜라 아르세노비크Nikola Arsenovic가 2003년 크로아티아의 민족 학 박물관Ethnographic Museum을 통해 출간한, 19세기 중반 이후 크로아티아인의 전통 복장을 담은 앨범에서 빌려 왔다. 그 책에는 크로아티아의 다른 지역의 복식과 일상생활에 관해서도 정밀 하게 채색된 삽화를 곁들여 설명하고 있다. 한편, 이 박물관은 AD 304년경 디오클레티아누스 Diocletian 황제가 퇴임 후 지냈던 궁전의 잔해가 위치한 로마의 중세 도시 안에 지어졌다. 드리니스drnis는 중세 고성의 잔해 위에 세워진 달마티아Dalmatia 섬의 작은 마을이다. 표지 그림 의 사내는 푸른색 울wool 바지와 하얀 섬유 셔츠, 지역 전통 복장이었던 색색의 자수가 놓인 푸 른색 울 조끼를 입고 있다. 손에는 긴 파이프를 들고 어깨에는 진홍빛 재킷을 대충 걸치고 있 다. 그리고 빨간 모자와 가죽 모카신moccasin으로 복장을 완성했다. 앨범 속의 시대 이후 200여 년이 흐르면서, 변화하는 복장 규정과 생활 양식에 맞춰 다채롭던 지역색도 점차 퇴색되었다. 이제는 몇 마일 떨어지지 않은 작은 마을이나 도시 사람은 말할 것 도 없고, 심지어 다른 대륙에 사는 사람 간에도 차이가 크지 않다. 우리는 아마도 문화와 외향 적 다양성을 더 다양하고 빠르게 변모하는 첨단 기술 생활이라는 개인의 다양성과 맞바꾸어 왔 으리라. 매닝은 2세기 전의 풍성했던 지역적 다양성을 빌려 컴퓨터 사업의 독창성과 창의력을 찬미하 고자, 이처럼 오래된 책과 모음집의 삽화를 다시 세상 밖으로 끄집어내어 표지 그림으로 활용 하고 있다. 표지 설명
  • 16. 16 CONTENTS 옮긴이 소개 .................................................................................................................... 4 지은이 소개 .................................................................................................................... 4 옮긴이의 말 .................................................................................................................... 5 지은이의 말 .................................................................................................................... 8 이 책에 대하여 .............................................................................................................. 10 표지 설명 ..................................................................................................................... 15 PART 1 기반 다지기 CHAPTER 1 좋은 테스트의 약속 1.1 더 좋은 테스트를 작성하기 위한 현황 점검 ......................................................................... 29 1.2 테스트의 가치 ............................................................................................................... 30 1.2.1 생산성에 영향을 주는 요소 ...................................................................................... 34 1.2.2 설계 잠재력 곡선 ................................................................................................... 36 1.3 설계 수단으로써의 테스트 ............................................................................................... 37 1.3.1 테스트 주도 개발 ................................................................................................... 37 1.3.2 행위 주도 개발 ...................................................................................................... 39 1.4 요약 ............................................................................................................................ 41 CHAPTER 2 좋은 테스트란? 2.1 읽기 쉬운 코드가 유지보수도 쉽다 .................................................................................... 45 2.2 구조화가 잘 되어 있다면 이해하기 쉽다 ............................................................................. 47 2.3 엉뚱한 걸 검사하는 건 좋지 않다 ...................................................................................... 50 2.4 독립적인 테스트는 혼자서도 잘 실행된다 ........................................................................... 51
  • 17. 17 2.5 믿음직한 테스트라야 기댈 수 있다 .................................................................................... 54 2.6 모든 일이 그렇듯 테스트에도 도구가 쓰인다 ....................................................................... 56 2.7 요약 ............................................................................................................................ 57 CHAPTER 3 테스트 더블 3.1 테스트 더블의 위력 ........................................................................................................ 61 3.1.1 테스트 대상 코드를 격리한다 ................................................................................... 62 3.1.2 테스트 속도를 개선한다 .......................................................................................... 64 3.1.3 예측 불가능한 실행 요소를 제거한다 ......................................................................... 64 3.1.4 특수한 상황을 시뮬레이션한다 ................................................................................. 65 3.1.5 감춰진 정보를 얻어낸다 .......................................................................................... 66 3.2 테스트 더블의 종류 ........................................................................................................ 68 3.2.1 테스트 스텁은 유난히 짧다 ...................................................................................... 68 3.2.2 가짜 객체는 뒤끝 없이 처리한다 ............................................................................... 70 3.2.3 테스트 스파이는 기밀을 훔친다 ................................................................................ 71 3.2.4 Mock 객체는 예기치 않은 일을 막아준다 .................................................................. 74 3.3 테스트 더블 활용 지침 .................................................................................................... 76 3.3.1 용도에 맞는 더블을 선택하라 ................................................................................... 76 3.3.2 준비하고, 시작하고, 단언하라 ................................................................................... 77 3.3.3 구현이 아니라 동작을 확인하라 ................................................................................ 78 3.3.4 자신의 도구를 선택하라 .......................................................................................... 79 3.3.5 종속 객체를 주입하라 ............................................................................................. 80 3.4 요약 ............................................................................................................................ 81
  • 18. 18 PART 2 테스트 냄새 CHAPTER 4 가독성 4.1 기본 타입 단언 .............................................................................................................. 87 4.1.1 예시 .................................................................................................................... 87 4.1.2 개선 방법 ............................................................................................................. 88 4.1.3 정리 .................................................................................................................... 90 4.2 광역 단언 ..................................................................................................................... 91 4.2.1 예시 .................................................................................................................... 91 4.2.2 개선 방법 ............................................................................................................. 94 4.2.3 정리 .................................................................................................................... 96 4.3 비트 단언 ..................................................................................................................... 96 4.3.1 예시 .................................................................................................................... 97 4.3.2 개선 방법 ............................................................................................................. 98 4.3.3 정리 .................................................................................................................... 98 4.4 부차적 상세정보 ............................................................................................................ 99 4.4.1 예시 .................................................................................................................... 99 4.4.2 개선 방법 ........................................................................................................... 101 4.4.3 정리 .................................................................................................................. 103 4.5 다중 인격 ................................................................................................................... 103 4.5.1 예시 .................................................................................................................. 104 4.5.2 개선 방법 ........................................................................................................... 104 4.5.3 정리 .................................................................................................................. 108 4.6 쪼개진 논리 ................................................................................................................ 108 4.6.1 예시 .................................................................................................................. 109 4.6.2 개선 방법 ........................................................................................................... 111 CONTENTS
  • 19. 19 4.6.3 정리 .................................................................................................................. 114 4.7 매직 넘버 ................................................................................................................... 115 4.7.1 예시 .................................................................................................................. 115 4.7.2 개선 방법 ........................................................................................................... 116 4.7.3 정리 .................................................................................................................. 117 4.8 셋업 설교 ................................................................................................................... 117 4.8.1 예시 .................................................................................................................. 118 4.8.2 개선 방법 ........................................................................................................... 119 4.8.3 정리 .................................................................................................................. 121 4.9 과잉보호 테스트 .......................................................................................................... 121 4.9.1 예시 .................................................................................................................. 122 4.9.2 개선 방법 ........................................................................................................... 123 4.9.3 정리 .................................................................................................................. 123 4.10 요약 ........................................................................................................................ 123 CHAPTER 5 유지보수성 5.1 중복 .......................................................................................................................... 127 5.1.1 예시 .................................................................................................................. 127 5.1.2 개선 방법 ........................................................................................................... 128 5.1.3 정리 .................................................................................................................. 131 5.2 조건부 로직 ................................................................................................................ 131 5.2.1 예시 .................................................................................................................. 132 5.2.2 개선 방법 ........................................................................................................... 133 5.2.3 정리 .................................................................................................................. 134 5.3 양치기 테스트 ............................................................................................................. 134 5.3.1 예시 .................................................................................................................. 135 5.3.2 개선 방법 ........................................................................................................... 136
  • 20. 20 5.3.3 정리 .................................................................................................................. 138 5.4 파손된 파일 경로 ......................................................................................................... 138 5.4.1 예시 .................................................................................................................. 139 5.4.2 개선 방법 ........................................................................................................... 140 5.4.3 정리 .................................................................................................................. 142 5.5 끈질긴 임시 파일 ......................................................................................................... 143 5.5.1 예시 .................................................................................................................. 143 5.5.2 개선 방법 ........................................................................................................... 144 5.5.3 정리 .................................................................................................................. 146 5.6 잠자는 달팽이 ............................................................................................................. 147 5.6.1 예시 .................................................................................................................. 147 5.6.2 개선 방법 ........................................................................................................... 148 5.6.3 정리 .................................................................................................................. 150 5.7 픽셀 퍼펙션 ................................................................................................................ 151 5.7.1 예시 .................................................................................................................. 151 5.7.2 개선 방법 ........................................................................................................... 153 5.7.3 정리 .................................................................................................................. 157 5.8 파라미터화된 혼란 ....................................................................................................... 158 5.8.1 예시 .................................................................................................................. 158 5.8.2 개선 방법 ........................................................................................................... 162 5.8.3 정리 .................................................................................................................. 165 5.9 메서드 간 응집력 결핍 .................................................................................................. 166 5.9.1 예시 .................................................................................................................. 166 5.9.2 개선 방법 ........................................................................................................... 168 5.9.3 정리 .................................................................................................................. 171 5.10 요약 ........................................................................................................................ 172 CONTENTS
  • 21. 21 CHAPTER 6 신뢰성 6.1 주석으로 변한 테스트 ................................................................................................... 177 6.1.1 예시 .................................................................................................................. 177 6.1.2 개선 방법 ........................................................................................................... 178 6.1.3 정리 .................................................................................................................. 179 6.2 오해를 낳는 주석 ......................................................................................................... 180 6.2.1 예시 .................................................................................................................. 180 6.2.2 개선 방법 ........................................................................................................... 181 6.2.3 정리 .................................................................................................................. 183 6.3 절대 실패하지 않는 테스트 ............................................................................................ 183 6.3.1 예시 .................................................................................................................. 184 6.3.2 개선 방법 ........................................................................................................... 184 6.3.3 정리 .................................................................................................................. 185 6.4 지키지 못할 약속 ......................................................................................................... 186 6.4.1 예시 .................................................................................................................. 186 6.4.2 개선 방법 ........................................................................................................... 189 6.4.3 정리 .................................................................................................................. 190 6.5 낮아진 기대치 ............................................................................................................. 191 6.5.1 예시 .................................................................................................................. 191 6.5.2 개선 방법 ........................................................................................................... 193 6.5.3 정리 .................................................................................................................. 193 6.6 플랫폼 편견 ................................................................................................................ 194 6.6.1 예시 .................................................................................................................. 194 6.6.2 개선 방법 ........................................................................................................... 195 6.6.3 정리 .................................................................................................................. 198 6.7 조건부 테스트 ............................................................................................................. 198 6.7.1 예시 .................................................................................................................. 199
  • 22. 22 6.7.2 개선 방법 ........................................................................................................... 200 6.7.3 정리 .................................................................................................................. 201 6.8 요약 .......................................................................................................................... 201 PART 3 여흥거리 CHAPTER 7 테스트 가능 설계 7.1 테스트 가능 설계란? .................................................................................................... 207 7.1.1 모듈러 설계 ........................................................................................................ 208 7.1.2 SOLID 설계 원칙 ................................................................................................ 209 7.1.3 맥락을 고려한 모듈러 설계 .................................................................................... 211 7.1.4 모듈러 설계를 위한 시운전 .................................................................................... 211 7.2 테스트 불가 원인 ......................................................................................................... 212 7.2.1 클래스 생성 불가 ................................................................................................. 212 7.2.2 메서드 호출 불가 ................................................................................................. 213 7.2.3 결과 확인 불가 .................................................................................................... 214 7.2.4 협력 객체 대체 불가 ............................................................................................. 214 7.2.5 메서드 오버라이딩 불가 ........................................................................................ 215 7.3 테스트 가능 설계를 위한 지침 ........................................................................................ 216 7.3.1 복잡한 private 메서드를 피하라 ............................................................................. 216 7.3.2 final 메서드를 피하라 ........................................................................................... 216 7.3.3 정적 메서드를 피하라 ........................................................................................... 217 7.3.4 new는 신중하게 사용하라 .................................................................................... 218 7.3.5 생성자에서는 로직 구현을 피하라 ........................................................................... 219 7.3.6 싱글톤을 피하라 .................................................................................................. 221 CONTENTS
  • 23. 23 7.3.7 상속보다는 컴포지션을 사용하라 ............................................................................ 223 7.3.8 외부 라이브러리를 감싸라 ..................................................................................... 223 7.3.9 서비스 호출을 피하라 ........................................................................................... 224 7.4 요약 .......................................................................................................................... 226 CHAPTER 8 제2의 JVM 언어를 활용한 테스트 작성 8.1 JVM 언어 혼용의 조건 ................................................................................................. 231 8.1.1 일반적인 이점 ..................................................................................................... 231 8.1.2 테스트 작성하기 .................................................................................................. 234 8.2 그루비로 단위 테스트 작성하기 ...................................................................................... 235 8.2.1 간소화된 테스트 셋업 ........................................................................................... 236 8.2.2 그루비로 작성한 JUnit 4 테스트 ............................................................................ 238 8.3 BDD 도구의 뛰어난 표현력 ........................................................................................... 240 8.3.1 easyb로 작성한 그루비 명세 ................................................................................. 240 8.3.2 테스트의 표현력을 높여주는 스폭 ........................................................................... 242 8.3.3 스폭의 또 다른 무기, 테스트 더블 ........................................................................... 244 8.4 요약 .......................................................................................................................... 246 CHAPTER 9 테스트 속도 개선 9.1 속도 개선을 위해서 ...................................................................................................... 251 9.1.1 더 빠르게! .......................................................................................................... 251 9.1.2 상황 속으로 ........................................................................................................ 252 9.1.3 빌드 프로파일링하기 ............................................................................................ 252 9.1.4 테스트 프로파일링하기 ......................................................................................... 256 9.2 테스트 코드 속도 높이기 ............................................................................................... 259
  • 24. 24 9.2.1 피곤하지 않다면 잠들지 말라 ................................................................................. 260 9.2.2 덩치 큰 기반 클래스를 경계하라 ............................................................................. 260 9.2.3 불필요한 셋업과 티어다운을 경계하라 ..................................................................... 263 9.2.4 테스트에 초대할 손님은 까다롭게 선택하라 .............................................................. 265 9.2.5 로컬하게, 그리고 빠르게 유지하라 .......................................................................... 266 9.2.6 데이터베이스의 유혹을 뿌리쳐라 ............................................................................ 268 9.2.7 파일 I/O보다 느린 I/O는 없다 ................................................................................ 269 9.3 빌드 속도 높이기 ......................................................................................................... 272 9.3.1 램 디스크를 활용한 초고속 I/O .............................................................................. 273 9.3.2 빌드 병렬화하기 .................................................................................................. 274 9.3.3 고성능 CPU에 짐 떠넘기기 ................................................................................... 280 9.3.4 빌드 분산하기 ..................................................................................................... 283 9.4 요약 .......................................................................................................................... 288 Appendix 부록 Appendix A JUnit 기초 A.1 기본적인 JUnit 테스트 케이스 ................................................................................. 293 A.2 JUnit 단언문 ........................................................................................................ 295 Appendix B JUnit 확장하기 B.1 러너를 통해 테스트 동작 제어하기 ............................................................................ 301 B.2 규칙으로 테스트 꾸미기 .......................................................................................... 303 B.3 기본 규칙들 .......................................................................................................... 303 CONTENTS
  • 25. 25 기반 다지기 Part I 1부는 여러분과의 첫 대면임을 생각해서 서로 간의 공감대를 확고히 형성하기 위한 내용으로 꾸며보았다. 이 책의 궁극적인 목표인 ‘좋은 테스트를 작성하는 능력 키우기’를 위한 첫 과정으로, 1장에서는 테스트를 작성해 서 얻을 수 있는 이점이 무엇인지 살펴본다. 이어서 프로그래머 생산성에 영향을 주는 요소를 알아보고, 그중 에서 특히 테스트와 테스트 품질이 미치는 영향에 관해 집중적으로 이야기할 것이다. 마무리로는 자동화된 테 스트와 밀접한 주제인 ‘테스트 주도 개발’(TDD)과 ‘행위 주도 개발’(BDD)을 소개하겠다. 2장에서는 좋은 테스트가 갖춰야 할 요건을 정의한다. 간단히 말해 가독성, 유지보수성, 신뢰성이 우수한 테스 트를 작성해야 한다. 이 주제는 2부에서 더 깊게 다뤄지는데, 원치 ‘않는’ 모습의 테스트라는 다른 관점에서 바 라본 예제를 검토하게 될 것이다. 1부의 마지막인 3장에서는 오늘날 프로그래머의 필수 도구로 떠오른 테스트 더블을 배워본다. 먼저, 테스트 더블로 할 수 있는 일을 알아본다. 예를 들어 테스트를 효율적으로 하기 위해 테스트 더블로 코드를 격리할 수 있다. 이어서 우리가 사용할 수 있는 테스트 더블의 종류별 차이점을 알아본다. 마지막으로는 테스트 더블의 장점을 최대한 살릴 수 있는 올바른 활용 지침을 준비하였다. 1부를 모두 읽고 나면 여러분이 작성하고 싶은 테스트의 모습과 그렇게 만들고 싶은 이유가 머릿속에 그려질 것이다. 더불어 그런 테스트를 만들 때 유용한 테스트 더블도 명확하게 이해하게 될 것이다. 이상의 기반을 토 대로 나머지 2부와 3부에서는 실무에 바로 활용할 수 있는 기술과 비법을 한 아름 안겨줄 것이다.
  • 26.
  • 27. 27 좋은 테스트의 약속 CHAPTER 1 이 장의 내용 ● 단위 테스트의 가치 ● 개발자 생산성을 향상하는 테스트 ● 설계 도구로써의 테스트
  • 28. 28 Part I 기반 다지기 내가 전문 프로그래머로 사회에 첫발을 내디뎠을 때만 해도 지금과는 사뭇 다른 세상이었다. 바 야흐로 10년도 더 지난 과거의 이야기다. 사람들은 이클립스Eclipse나 넷빈즈NetBeans, 아이디어IDEA 와 같은 통합 개발 환경이 아닌 빔Vim이나 이맥스Emacs 같은 텍스트 편집기로 코드를 작성하고 있었다. 이맥스 매크로를 마구 휘둘러 수천, 수만의 System.out.println 문을 생성해대며 디 버깅하던 직장 선배의 모습이 아직도 눈에 선하다. 그리고 주문이 제대로 처리되지 않는 버그 덕분에, 그 많은 println이 내뱉은 로그를 해독하느라 고생하던 나의 모습은 더욱 생생하다. 프로그래머 대부분이 테스트를 코딩이 끝나면 다른 사람이 해주는 일 혹은 코딩을 다 끝냈다고 선언하기 전에 자신이 짠 코드를 이리저리 찔러보는 일 정도로 치부하던 시절이다. 그러다가 버그가 발견되면, 잘못된 곳을 찾기 위해 로그를 조금씩 추가하며 코드를 들쑤시는 모습이 친 근한 일상이었다. 자동화는 당시의 우리에게는 신선한 개념이었다. 컴파일과 패키징 정도는 메이크파일makefile로 자동화해뒀지만, 빌드할 때마다 테스트까지 함께 돌리지는 않았다. 그 대신에 한두 개의 테스 트 클래스를 실행하는 셸 스크립트를 여러 개 만들어 썼다. 테스트 클래스라고는 했지만, 사실은 제품 코드를 실행해서 결과를 화면에 뿌려주는 간단한 애플리케이션에 지나지 않았다. 실패한 단언 모두를 알려주는 오늘날의 테스트 프레임워크와 자가검증self-verifying 테스트와는 비교할 바 가 못 된다. 그 후로 많은 시간이 흘렀다. 좋은 테스트의 약속 CHAPTER 1
  • 29. 29CHAPTER 1 좋은 테스트의 약속 1.1 더 좋은 테스트를 작성하기 위한 현황 점검 자동화된 테스트는 개발자가 직접 작성해야 하고, 그중 하나라도 실패하면 빌드 전체가 실패한 것이란 인식은 이제 꽤 널리 퍼져있다. 나아가, 테스트 선행 방식의 프로그래밍을 실천하는 개 발자 수도 점점 늘고 있다. 테스트 선행 방식에서는 자동화된 테스트를 단순한 오류 예방 목적 으로뿐 아니라, 코딩 전에 그 코드에 기대하는 동작을 정의하는 설계 보조 수단으로까지 활용 한다. 구현까지 다 끝나야 검증을 시작하는 게 아니라 애초에 설계부터 검증하고 들어가는 것 이다. 개인적으로는 컨설턴트로 활동하면서 수많은 팀과 조직, 제품, 코드를 접해왔다. 그런데 요즘 주 변을 둘러보면 자동화된 테스트는 이미 주류로 편입된 것이 확실하다. 자동화된 테스트 없이는 대부분의 소프트웨어 프로젝트의 상황이 지금보다 훨씬 열악했을 것이 분명하니 확실히 올바 른 길로 나아가는 중이다. 자동화된 테스트는 여러분의 생산성을 높이고 개발 속도를 빠른 상 태로 유지해준다.1 도와줘! 단위 테스트는 처음이란 말이야. 자동화된 테스트 작성에 익숙하지 않은 독자라면 바로 지금이 배울 수 있는 절호의 기회다. 매닝(Manning)에 서는 자바 단위 테스트계의 사실상 표준 프레임워크인 JUnit 관련 책을 다수 내놓았다. 그중에서도 『JUnit in Action』1 은 POJO(Plain Old Java Object)부터 엔터프라이즈 자바빈즈(Enterprise JavaBeans)에 이르는 온갖 자바 코드를 테스트하는 방법을 가르쳐주는 훌륭한 참고서가 될 것이다. 자바와 JUnit만 처음일 뿐 단위 테스트 자체는 좀 작성해보았다면 ‘부록 A - JUnit 기초’를 가볍게 훑어보는 정도면 이 책에 담긴 지혜를 모두 얻어가는 데 부족함은 없을 거다. 자동화된 테스트가 널리 퍼졌다고 해서 테스트 커버리지가 매우 높다거나 개발 생산성을 더 이 상 끌어올리기 어렵다는 의미는 절대 아니다. 사실 나는 지난 5년여 동안 다른 개발자에게 테 스트를 작성하게 하고, 구현에 앞서 테스트부터 만들게 했으며, 특히 더 좋은 테스트를 작성하 게 도와주며 많은 시간을 보냈다. 테스트를 더 잘 작성해야 한다고 이토록 강조하는 이유는 뭘까? 테스트 품질을 등한시하면 어 떤 일이 벌어질까? 이제부터 테스트가 주는 가치와 테스트 품질의 중요성에 관하여 본격적으 1 저자주_ 피터 타치브 등, 매닝, 2010. 번역서 『JUnit in Action 단위 테스트의 모든 것』 (이복연 역, 인사이트, 2011)
  • 30. 30 Part I 기반 다지기 로 이야기를 시작해보겠다. 1.2 테스트의 가치 촉망받는 프로그래머 마커스를 소개한다. 그는 2년 전에 대학을 졸업하고, 지역 투자 은행의 IT 부서에 입사하여 온라인 셀프서비스 웹 애플리케이션을 개발해왔다. 입사 초기에는 팀의 막 내로서 은행 관련 지식을 쌓고 선배들이 일하는 방식을 파악하는 데 힘썼다. 입사 후 몇 달도 채 지나지 않아, 마커스는 팀이 프로그래머의 실수2 를 바로잡기 위한 재작업에 상당한 시간을 허비하고 있다는 사실을 알아차렸다. 지금껏 수정해온 실수의 유형을 주의 깊게 살펴보니, 그 대부분은 간단한 단위 테스트만으로도 쉽게 잡을 수 있을 것 같았다. 그래서 마커 스는 실수하기 쉬워 보이는 코드를 찾아 이곳저곳에 단위 테스트를 작성해 넣기 시작했다. 테스트는 실수를 바로잡아준다. 시간이 흐르자 다른 팀원 역시 서서히 단위 테스트를 작성하기 시작했다. 마커스는 이른바 테스 트 추종자3 가 되었고, 그가 작성한 코드 대부분은 자동화된 테스트로 매우 높은 커버리지를 달성 하였다. 오류 수정에 쏟는 시간이 늘어난 것도 아닌데 미해결 결함의 수는 점차 줄어들었다. 테 스트가 팀의 작업 품질에 가시적인 영향을 주기 시작한 것이다. 마커스가 코드베이스에 첫 번째 테스트를 추가한 이후로 근 1년이 흘렀다. 마커스는 크리스마 스 파티 장소로 향하며 지금까지 경험한 변화를 되짚어보았다. 그런데 팀 전체의 테스트 커버리 지는 계속 빠르게 상승해오다가 최근 몇 주에서 몇 달간은 98%를 정점으로 큰 변화가 없었다. 마커스는 한동안 이 수치를 100%까지 끌어올려야 한다는 생각에 사로잡혀 있었다. 하지만 최 근 몇 주 사이에 마음을 바꿔먹었다. 아직 채워지지 않은 테스트가 가져다줄 가치가 그리 크지 않아서 테스트 작성에 힘을 더 쏟아봤자 돌아오는 소득이 별로 없어 보였다. 아직 검증되지 않 은 코드는 마커스 팀에서는 사용하지 않는 인터페이스를 구현해야 하는 API가 대부분이었다. 이런 껍데기 메서드를 검사해서 무엇하겠는가? 2 저자주_ ‘오류(error)’, ‘결함(defect)’, ‘버그(bug)’, ‘문제(issue)’라고도 한다. 3 저자주_ 테스트 추종자(test-infected)란 용어는 1998년 Java Report에 실린 에릭 감마(Erich Gamma)와 켄트 벡의 기고문 『Test-Infected: Programmers Love Writing Tests』 (테스트 추종자: 테스트 작성을 사랑하는 프로그래머들)에서 처음 사용되었다.
  • 31. 31CHAPTER 1 좋은 테스트의 약속 100% 코드 커버리지 달성이 중요한 게 아니다. 95%보다는 100%가 물론 듣기 좋다. 다만, 그 차이는 그리 크지 않을 수 있다. 테스트의 가치는 테스트가 확인 하지 못한 코드가 어떤 것인가와 테스트가 프로그래밍 실수를 얼마나 정확하게 잡아내는가에 좌우된다. 100% 를 달성했다고 해서 결함이 없다고 보장해주는 건 아니다. 애플리케이션 동작이 올바른가와는 상관없이, 그저 모 든 코드를 한 번씩은 실행해보았다는 것만을 보장할 뿐이다. 그러니 커버리지에 대한 강박관념은 버리고 의미 있 는 테스트를 작성하는 데 집중하기 바란다. 그림 1-1 테스트 수가 많아질수록 새로 추가한 테스트의 가치는 떨어진다. 왜냐하면, 개발자 는 일반적으로 가장 핵심적인, 이를테면 가장 중요하고 위험 부담이 큰 코드를 먼저 검사하기 때문이다. 그와 달리 대부분의 테스트를 작성한 후에도 확인하지 않은 코드는 십중팔구 가장 사소하고 문제될 소지가 적은 부분이다. 테스트 작성에 쏟아 부은 노력 테스트의가치 마커스의 팀은 고지에 올라선 것이다. 고지란 [그림 1-1]에서 곡선의 평평한 윗부분을 말하는 데, 투자한 노력 대비 돌아오는 이익이 감소하는 구간이다. 개인적으로 자바 사용자그룹에서 만난 많은 팀이 이와 같은 현상을 경험해보았다고 말했다. 마커스의 생각을 바꿔준 사람은 세바스찬이었다. 그는 이전에 마커스가 일하는 투자 은행에도 컨설팅해준 바 있는 경험 많은 소프트웨어 아키텍트였다. 세바스찬은 셀프서비스 팀에 합류한 직후 마커스를 비롯한 새내기 팀원의 멘토가 되어주었다. 그는 웹 애플리케이션 개발에 많이 쓰이는 프로그래밍 언어에도 능숙했지만, 마커스가 단위 테스트를 작성하는 방식에 특히 많은 영향을 주었다. 지금까지 마커스는 새 코드 작성 시 단위 테스트 작성까지 마친 후 버전 관리 시스템에 체크인 하는 습관을 길러왔다. 그런데 세바스찬의 방식은 좀 특이했다. 실패할 게 뻔한 테스트를 먼저 하나 만들고, 그 테스트가 성공할 만큼의 코드를 작성했다. 그리곤 다시 실패할 테스트를 또 하
  • 32. 32 Part I 기반 다지기 나 작성하는 식이다. 작업을 완료할 때까지 계속 이런 식이었다. 세바스찬과 함께하며 마커스는 자신의 프로그래밍 방식도 조금씩 개선됨을 느꼈다. 객체를 구 성하는 방식도 바뀌었고 완성된 코드도 어딘가 달라 보였다. 코드의 설계와 기능을 사용자의 시각에서 바라보기 시작한 까닭이다. 테스트는 실사용에 적합한 설계를 끌어내준다. 마커스는 마치 머릿속에서 전구가 ‘팍!’ 하고 켜진 것 같은 느낌이었다. 그는 달라진 프로그래밍 방식과 결과를 말로 표현하는 과정에서, 테스트가 단순한 품질 보증이나 실수 재발 방지 수단 만은 아님을 깨달았다. 테스트는 분명 코드를 설계하는 한 방식이기도 했다. 실패할 테스트를 거쳐 간 코드는 분명 필요한 기능을 모두 담고 있으면서도 이전 방식으로 작성한 코드보다 훨씬 간 결했다. 테스트는 원하는 동작을 명확히 알려주어 군더더기(gold-plating)를 없애준다. 이야기의 주인공인 마커스의 경험은 실제로 많은 테스트 추종 개발자가 테스트를 개발하며 깨 닫고 이해하는 과정을 그린 것이다. 처음에는 시간을 좀먹는 부끄러운 실수를 예방할 생각으로 자동화된 단위 테스트를 작성하기 시작한다. 그리고 시간이 지날수록 안전장치로써의 역할은 전체 그림의 일부일 뿐임을 깨닫게 된다. 오히려 테스트를 코딩에 접목하면서 경험하는 사고 과정이 더 가치 있을 것이다. 자동화된 단위 테스트는 개발자가 직접 작성해야 한다는 인식은 이미 널리 퍼져있지만, 어떤 테스트를 얼마나 많이 작성해야 하는가에 대한 인식은 여전히 부족하다. 개인적인 컨설팅 경험 에 비추어봐도 테스트의 필요성을 이해하지 못하는 프로그래머는 거의 없었다. 하지만 제품 코 드의 모든 경로를 훑고 있음을 의미하는 100% 코드 커버리지 달성을 주장하는 프로그래머는 거의 없었다. 여기서 얻을 수 있는 결론은 무엇일까? 테스트를 작성해야 한다는 데에는 누구나 동의하지만, 커버리지가 100%에 근접해질수록 테스트를 더 작성해야 하는가에 대해서는 확신이 줄어든다. 작성할 테스트를 거의 다 작성했다면 나머지 코드에서 문제가 발견될 가능성은 낮아지기 때문 이다. 이것이 바로 수확 체감diminishing return이라는 것으로 [그림 1-1]의 곡선이 잘 나타내주고 있다. 결국, 신중히 고민해서 만든 첫 100개의 테스트로는 개선 효과가 피부로 느껴지겠지만, 이미
  • 33. 33CHAPTER 1 좋은 테스트의 약속 30,000개나 갖춰진 상태에서는 100개를 더 만드는 것으로는 변화를 체감하기 어렵다. 하지만 마커스가 멘토를 통해 깨달은 것처럼 여기서 끝이 아니다. 우리 앞에는 아직 두 번째 고지가 남아 있다. 테스트를 작성해서 얻게 되는 가장 큰 수확은 테스트 자체가 아니다. 작성 과정에서 얻는 깨달음이다. 마커스 이야기에서는 테스트를 바라보는 두 가지 인식을 강조했다. 두 개의 고지란 바로 그 각각 의 인식을 기반으로 테스트를 작성했을 때 도달할 수 있는 최고 경지를 뜻한다. 물론 테스트의 잠재 가치를 모두 일깨우려면 [그림 1-2]의 고지 두 곳을 모두 점령해야 한다. 그림 1-2 처음 도달할 수 있는 낮은 고지에 이르면 테스트를 추가하고 개선해도 더 이상의 가 치를 끌어내기 어려워진다. 그 위의 두 번째 고지는 테스트가 단순한 검증 수단 이상임을 깨닫 는 사고의 전환을 통해야만 발견할 수 있는 더 높은 경지다. 테스트를 설계 수단으로 이용할 경우 테스트를 품질 보증 수단으로만 이용할 경우 테스트 작성에 들인 노력 테스트의가치 테스트를 품질 보증 수단으로만 인식하는 한 얻을 수 있는 잠재적 가치는 [그림 1-2]의 낮은 곡선을 벗어날 수 없다. 사고의 틀을 깨고 테스트를 프로그래밍 도구, 즉 설계 도구로 인식하는 순간 품질 고지를 뛰어넘어 설계 고지에 도달하는 길이 열리게 된다. 불행하게도 테스트로 설계한다는 인식 전환 단계를 통과하지 못한 개발자가 훨씬 많아서 대부분 의 제품 코드는 첫 번째 곡선 어딘가에 머물러 있다. 마찬가지로 개발자는 커지는 테스트 스위 트test suite 관리 비용에도 별로 관심을 두지 않는다. 이쯤에서 질문이 하나 떠오른다. 프로그래머 생산성에 영향을 주는 요소에는 무엇이 있고, 그 안에서 단위 테스트의 역할은 무엇일까?
  • 34. 34 Part I 기반 다지기 1.2.1 생산성에 영향을 주는 요소 테스트를 빠르게 작성하려면 무엇이 중요한가는 신경 쓰지 않고 열심히 타이핑만 하면 된다. 하지만 많은 사람들이 테스트를 작성하느라 시간을 쏟고, 중복을 없애고, 구조와 명료성은 물 론 유지보수에까지 신경을 쓰는 데는 그만한 이유가 있다. 테스트 코드는 제품 코드보다 간결한 게 보통이다.4 그렇다 해서 테스트 코드를 허투루 작성하 고 문제를 심어 놓으면, 나중에 분명 발목 잡힐 날이 올 거다. 중복도 많고 쓸데없이 복잡한 테 스트 코드는 생산성을 떨어뜨리고 테스트의 긍정적 효과마저 앗아간다는 걸 명심하자. 엉터리로 작성한 테스트 코드는 가독성만이 아니라 안정성과 신뢰성, 실행 속도에도 악영향을 준다. [그림 1-3]은 개발자 생산성에 영향을 주는 요소의 역학 구조를 테스트 관점에서 바라본 모습이다. 생산성에 직접 영향을 주는 피드백 주기와 디버깅 시간에 주목해보자. 경험상 이 두 가지가 가장 유력한 야근의 요정이다.5 실수하자마자 곧바로 알아차릴 수만 있다면 지루한 디버깅을 상당수 피할 수 있지만, 피드백 주기가 길어질수록 디버깅 시간도 길어지게 마련이다. 그림 1-3 테스트는 다방면에 걸쳐 생산성에 직간접적인 영향을 준다. 피드백 주기의 길이 개발자 생산성 디버깅 결함 테스트 신뢰성 테스트 결과의 정확성 테스트 안정성 단축시킨다. 감소시킨다. 피하게 한다. 예방한다. 예방한다. 유발한다. 향상시킨다. 향상시킨다. 감소시킨다. 테스트 실행 속도 테스트 가독성 4 저자주_ 예를 들어 조건문이나 반복문을 사용하는 테스트는 많지 않다. 5 저자주_ 생산성 저하의 끝판왕은 회의라고들 얘기하지만, 그에 관해서는 다른 책을 찾아보길 바란다.
  • 35. 35CHAPTER 1 좋은 테스트의 약속 버그 수정 비용의 증가 버그 수정 비용은 평균적으로 얼마나 될까? 런던에서 열린 ‘XP Day 2009 컨퍼런스’에서 마크 스트리에벡 (Mark Striebeck)은 구글에서 결함을 수정하기 위해 지연된 시간을 비용으로 계산해서 공개하였다. 구글이 측정한 바로는 프로그래머가 버그를 만들자마자 즉시 수정한다면 $5를 쓴 것이다. 같은 결함을 프로 젝트 전체 빌드 때 발견하면 비용은 $50가 된다. 만약 통합 테스트까지 살아남으면 $500로 증가하며 시스템 테스트에 이르면 $5,000까지 치솟는다. 이 수치만 봐도 문제는 가능한 한 빨리 발견해야 한다는 건 이론의 여지가 없다. 테스트 실행 속도는 변경사항을 검증하고 확인validation and verification하기 위해 기다리는 시간에 직결 된다. 이 역시 주요한 요소라 그림에서도 굵게 강조해 두었다. 나머지 주요 요소 세 개는 모두 프로그래머가 해야 할 디버깅의 양과 관련이 있다. 가독성이 떨어지면 자연스럽게 분석이 더뎌지고 디버거를 사용해야 할 상황까지 만들 수 있다. 테스트 코드를 읽어봐도 무슨 말인지 이해하기 어렵기 때문이다. 이처럼 가독성이 안 좋으면 실수한 곳을 찾기 어려워 더 많은 결함이 만들어지고, 늘어난 결함은 디버깅 시간 증가로 이어 진다. 테스트 결과의 정확성도 발견하지 못하고 놓치는 결함의 수에 많은 영향을 준다. 실수로 결함을 만들어도 테스트 스위트가 찾아줄 거라며 믿고 의지하고 싶다면 정확성이라도 반드시 보장되 어야 한다. 생산성에 영향을 주는 나머지 요인인 신뢰성trustworthiness과 안정성reliability이 바로 이 테 스트 정확성과 직접 연관되어 있다. 테스트 결과를 믿고 싶다면 테스트가 약속한 것을 확실히 잡아내고 몇 번을 수행해도 항시 같은 결과가 나오도록 만들어야 한다. 이상의 생산성 역학 구조를 잘 이해하면 여러분도 품질 고지에 올라설 수 있다. 바로 이 요소들 이 개발자 생산성을 올려주는 핵심이기 때문이다. 또한, 생산적인 개발자가 되려면 마땅히 필 요한 도구도 능숙하게 다룰 줄 알아야 한다. 프로그래밍 언어의 기초를 다 익혔다면 표준 API 도 둘러보자. 문제에 대해 충분히 파악했다면 그 근본 원인을 파헤쳐보자. 바로 가독성, 안정 성, 신뢰성, 그리고 테스트 속도 말이다. 이들 원인은 책의 나머지 대부분에서 풀고자 하는 숙제이기도 하다. 즉 읽기 쉽고, 신뢰가 가고, 안정된 테스트 코드를 식별하는 능력을 키워주고, 그러한 테스트 코드를 만들고 관리할 수 있 도록 해주겠다.
  • 36. 36 Part I 기반 다지기 본격적인 논의에 앞서 [그림 1-2]의 두 번째 곡선이 뜻하는 바를 생각해보자. 1.2.2 설계 잠재력 곡선 제품 코드의 가장 대표적인 시나리오와 구조상 가장 치명적인 부분을 먼저 검사했다고 치자. 테스트 품질도 상급이고 철저한 리팩토링으로 중복까지 말끔히 제거해서 가볍고 유지보수도 쉬워졌다. 이어서 나머지 주요 기능을 모두 검사하고 getter/setter 등의 사소한 기능만 남았 다. 테스트 커버리지가 높은 것은 당연하다. 이 상태에서 마지막 남은 사소한 테스트는 작성해 봤자 큰 가치가 없다. 이는 수확 체감에 다다랐다는 신호로, 단지 테스트만 작성해서 얻을 수 있 는 가치의 한계점에 도달한 것이다. 이곳이 바로 일반적인 방식으로 도달할 수 있는 최고점인 품질 고지다. 그 한계를 뛰어넘어 한 차 원 높은 생산성을 맛보고자 한다면 환골탈태를 거쳐야 한다. 즉, 지금까지 가지고 있던 테스트 에 관한 사고의 틀을 깨야만 한다. 완전히 색다른 테스트의 가치를 찾아내야 숨어 있는 잠재력 을 끌어낼 수 있다. 실수가 반복되는 것을 예방한다는, 방어적이고 검증 지향적인 가치가 아닌, 더 창조적이고 설계 지향적인 가치가 바로 그것이다. 요약하면, 테스트의 잠재 가치를 전부 끌어내고 두 고지를 모두 정복하려면 다음처럼 하면 된다. 1 테스트 코드도 제품 코드를 다루듯 하라. 믿고 의지할 수 있을 만큼 철저하게 리팩토링하고 높은 품질을 유지하라. 2 테스트를 제품 코드가 목적과 쓰임새에 적합한 구조가 되게끔 이끌어주는 설계 수단으로 활용하라. 프로그래머 대부분이 잘 지키지 못하는 쪽은 첫 번째다. 테스트를 작성하고 관리하고 실행하는 비용을 최소화하는 동시에 고품질의 테스트 코드를 작성하는 걸 힘들어한다. 다행히도 이는 본 책에서 집중해서 다룰 주제인 좋은 테스트 작성하기의 영역이다. 달리 말하면, 설계 수단으로써의 테스트 쪽에는 많은 지면을 할애하지 않겠다는 뜻이다.6 그래 도 전반적인 역학과 작동 원리는 이해할 수 있도록 1.3절을 준비했다. 그럼 한번 시작해보자. 6 저자주_ 필자가 저술한 『Test Driven』 (매닝, 2007)은 이 주제에 딱 맞는 책이다. 스티브 프리먼(Steve Freeman)과 넷 프라이스(Nat Pryce)가 저술한 『Growing Object-Oriented Software, Guided by Tests』 (Addison-Wesley, 2009)를 참고해도 좋다.
  • 37. 37CHAPTER 1 좋은 테스트의 약속 1.3 설계 수단으로써의 테스트 프로그래머가 작성한 자동화된 테스트는 전통적으로 크게 두 가지 목적을 위한 품질보증 수단 이었다. 첫째는 코드를 작성하는 즉시 정확하게 구현했는지 검사하는 것이고, 둘째는 그 후에 코드베이스가 커져도 계속 잘 동작하는지 지속해서 확인하는 것이다. 설계하고, 설계대로 코딩 하고, 생각대로 잘 구현되었는지 확인하는 것으로, 테스트를 검증 수단으로 활용하는 전형적인 모습이다. 자동화된 테스트를 설계 수단으로 이용하기 시작하면 모든 것이 뒤바뀐다. 테스트를 코드 설계 용으로 사용하면 익숙했던 설계, 코딩, 테스트의 순서가 테스트, 코딩, 설계로 바뀐다. 잘못 읽은 게 아니다. 테스트가 코딩보다 선행되고 설계로 마무리된다. 마지막의 설계 단계는 리팩토링이라는 이름으로 더 유명하다. 결과적으로 [그림 1-4]와 같은 테스트 → 코딩 → 리팩토링의 순서가 된다. 그림 1-4 테스트 주도 개발 프로세스는 실패하는 테스트를 작성하는 것으로 시작하여, 테스트를 성공하게 만드는 코드를 작성하고, 작성된 코드의 설계를 개선하는 리팩토링으로 마무리된다. 테스트 코딩 (반복) 리팩토링 지금 하는 얘기가 친숙하게 느껴진다면 아마도 테스트 선행 프로그래밍이나 테스트 주도 개발에 대해 들어봐서일 것이다.7 마침 우리도 그 얘기를 하는 중이니 원래의 이름대로 부르기로 하자. 1.3.1 테스트 주도 개발 [그림 1-5]의 테스트 주도 개발TDD은 간단한 아이디어에서 시작된 프로그래밍 훈련법이다. ‘코 드가 갖춰야 할 기능을 명시하는, 실패하는 테스트 없이는 코드를 작성하지 않는다.’ 이것이 바 로 테스트 선행 프로그래밍이라 불리는 이유다. 7 저자주_ 혹은 몇 페이지 전에 읽은 마커스와 세바스찬 이야기 때문일 지도 모르겠다.
  • 38. 38 Part I 기반 다지기 그림 1-5 테스트 주도 개발에서는 실패하는 테스트 작성하기, 테스트 통과하기, 중복을 줄이고 의도를 명확하 게 하기 위한 코드 리팩토링을 반복한다. 그리고 도중에 문제가 생기지는 않았는지 확인하기 위해 매 단계 테스 트를 실행한다. 새로운 테스트를 작성한다. 모든 테스트를 실행한다. 모든 테스트를 실행한다. 리팩토링 이전으로 복원한다. 모든 테스트를 실행한다. 테스트 통과? 테스트 통과? 제품 코드와 테스트 코드를 리팩토링한다. 테스트 통과? 시작 예 아니요 예 예 아니요 아니요 테스트를 만족시키는 제품 코드 작성한다. 테스트를 먼저 작성하면 소위 테스트로 설계한 제품 코드가 만들어진다. 여기에는 다음과 같은 긍정적인 효과가 따라온다. ● ‘사용 가능한 코드가 만들어진다.’ 즉, 제품 코드의 설계와 API가 활용 시나리오에 적합한 모습으로 거듭난다. ● ‘코드가 가벼워진다.’ 실제로 활용할 시나리오에서 요구하는 기능만을 담게 된다. 첫째, 프로젝트 진척도나 필요한 다른 컴포넌트, 클래스, 인터페이스가 갖춰져 있는지와 상관 없이 여러분의 손에는 항시 명확한 사용 시나리오가 딸린 설계만이 쥐어져 있게 된다. 더구나, 그 시나리오는 자동화된 단위 테스트라는 구체적이고 실행 가능한 형태로 구현되어 있다. 그래 서 테스트에 실패한다는 것은 테스트가 통과하도록, 아니 딱 통과할 정도만 제품 코드를 손봐 주라는 명확한 목표가 되어준다. 실행할 수 있는 테스트 코드로 시나리오를 그려내는 일은 분명 설계 영역에 속한 활동이다. 테 스트 코드는 제품 코드를 사용하는 고객의 입장이 되어 코드 한 줄 쓰기도 전에 설계가 올바로 되었는지 검증해준다. 요구사항을 구체화한 이 예제는 아주 강력한 검증 도구로, 오직 테스트 를 설계 수단으로 활용할 때만 얻을 수 있는 이점이기도 하다.
  • 39. 39CHAPTER 1 좋은 테스트의 약속 둘째, 테스트를 통과할 만큼만 코딩한다는 규칙을 잘 따라주면 설계를 간결하면서도 목적에 딱 맞도록 유지할 수 있다. 시나리오를 갖추지 못한 코드가 단 한 줄도 없으므로 버릴 게 하나도 없다. 반면 우발적 복잡성accidental complexity은 코드 품질을 떨어뜨리는 가장 악명 높은 적이자 개발 자 생산성을 갉아먹는 주 요인이다. 우발적 복잡성이란 쓸데없이 복잡한 것을 말한다. 다시 말해 요구조건은 그대로 만족하면서도 더 단순한 설계로 대체할 수 있다는 뜻이다. 프로그래머는 종종 자신도 이해하기 어려운 복잡 한 설계를 만들어서 자신이 얼마나 똑똑한지 보여주고 싶어한다. 여러분 내면에도 이와 같은 원초적 본능이 꿈틀대고 있을 것이다. 하지만 설계가 복잡해질수록 생산성이 떨어지는 건 당연 하므로, 불필요하게 복잡하게 만드는 건 정말 쓸데없고 비생산적이다. 결함이나 빠진 기능을 명시하는 테스트, 테스트를 통과할 만큼의 코드만 작성한다는 규칙, 그 리고 간결한 설계8 를 지향하는 철저한 리팩토링은 우발적 복잡성을 크게 줄여준다. 물론 만병 통치약이 될 순 없다. 최종 결과는 결국 프로그래머의 설계 감각과 경험에 크게 좌우되기 때문 이다. TDD는 사실 책 몇 권은 거뜬히 써낼 수 있을 만큼 거대한 큰 주제다. 필자가 저술한 『Test Driven』과 스티브 프리먼과 넷 프라이스가 최근에 쓴 『Growing Object-Oriented Software, Guided by Tests』 등이 그 예다. 개인적으로는 제목부터 간결한 켄트 벡Kent Beck의 『Test Driven Development: By Example』9 를 추천한다. TDD 관련 자료는 주변에서 쉽게 찾을 수 있으니 본 책에서는 여기까지만 이야기할 테니, 더 깊이 있는 설명이 필요한 독자는 직접 구해보길 바란다. 다만 TDD 관련 영역 중에서도 우리의 핵심 주제인 좋은 테스트와 밀접한 행위 주도 개발은 그냥 지나칠 수 없었다. 1.3.2 행위 주도 개발 행위 주도 개발BDD, Behavior-driven development이란 말을 들어봤는지 모르겠다. 사람들이 테스트 선 행 방식으로 프로그래밍하기 시작한 건 족히 수십 년은 되었지만, 우리가 알고 있는 테스트 주 8 저자주_ 간결한 설계(simple design)는 필요한 기능마저 수행하지 못할 만큼 지나치게 단순화한 설계(simplistic design)와는 전혀 다 른 개념이다. 9 저자주_ Addison-Wesley, 2002. 번역서 『테스트 주도 개발』 (김창준/강규영 역, 인사이트, 2005)
  • 40. 40 Part I 기반 다지기 도 개발은 1990년대에 와서야 이름이 생기고 체계를 갖추게 되었다. 약 10여 년이란 세월이 더 흘러, 댄 노스Dan North라는 런던의 컨설턴트는 차세대 테스트 선행 프 로그램을 주도하는 선두에 서게 된다. 그는 TDD에서 말하는 테스트라는 용어가 사람들을 잘못 된 길로 인도함을 깨달았다. 그래서 자신만의 TDD 방식을 만들고 행위 주도 개발이라는 이름 을 붙였다. 그는 2006년 『Better Software』에 기고한 글에서 행위 주도 개발을 다음과 같이 설명하였다. 문득 TDD에 대한 사람들의 오해 대부분은 테스트라는 단어 때문이라는 생각이 스쳤다. 테스트가 TDD의 본질이 아니라고 주장하는 게 아니다. 테스트 메서드가 코드의 동작을 보 장하는 효과적인 방법인 건 확실하다. 그런데 그 테스트가 시스템의 행위를 올바로 기술하 지 못한다면, 분명 잘못이 있는데도 개발자는 아무 문제 없다고 믿는 상황을 만든다. 나는 TDD에서 테스트가 들어가야 할 자리를 행위Behavior로 바꿔 사용하기 시작했다. 그러자 어휘적으로도 쏙 와 닿을 뿐 아니라 다른 사람을 가르치며 자주 받았던 질문들이 거짓말처 럼 해결되었다. 나는 이제 TDD와 관련된 질문 몇 가지의 해답을 알게 되었다. 테스트의 이 름을 짓는 건 정말 쉬워졌다. 검사하려는 행위를 기술하는 문장이면 된다. 테스트할 범위를 정하는 문제의 답도 간단하다. 답은 한 문장으로 기술할 수 있는 만큼의 행위다. 테스트가 실패하면 어떻게 해야 할까? 앞서 기술한 방식만 잘 따르면 된다. 새로운 버그가 만들어졌 건 행위가 바뀌었건 테스트가 더는 유효하지 않게 되었건 달라질 건 전혀 없다. 생각의 초점을 테스트에서 행위로 옮기는 것이 대단한 발견임을 깨달은 후부터 나는 TDD 를 BDD 혹은 행위 주도 개발이라 부르기 시작했다. 댄이 BDD라는 용어를 들고 와 전파하기 시작하자 전 세계 소프트웨어 개발 커뮤니티의 개발자 가 예제 주도example-driven, 행위명세 지향specification-of-behavior oriented 등 댄의 BDD를 구체화한 아 이디어를 발전시켜 나갔다. 나아가 요즘에는 코딩 외의 분야에서도 BDD라는 용어가 사용되 고 있다. 대표적으로는 요구 사항 단계의 비즈니스 분석과 명세화 시에 BDD를 사용한다. BDD 실천자가 보장하는 특이한 개념으로 인수 테스트를 통한 ‘외부로부터의’ 개발이 있다. 『The Cucumber Book: Behaviour-Driven Development for Testers and Developers』의 저자인 매트 윈Matt Wynne과 애슬랙 헬러조이Aslak Hellesøy의 설명을 들어보자. 행위 주도 개발은 최고의 TDD 실천자들의 좋은 습관을 정형화하여 만들어낸 TDD 기반
  • 41. 41CHAPTER 1 좋은 테스트의 약속 방법론이다. 최고의 TDD 실천자들은 외부로부터의 개발 방식을 사용한다. 즉, 그들이 가 장 먼저 작성하는, 실패하는 테스트는 시스템의 행위를 고객의 관점에서 서술한 인수 테스 트라고 할 수 있다. BDD 실천자로서 우리는 팀원 누구라도 쉽게 읽고 이해할 수 있도록 신 경 써서 인수 테스트를 작성한다. 이렇게 작성된 사용 예를 비즈니스 관계자에게 건네서 본 격적인 구현에 앞서 우리가 만들려는 방향이 올바른지 확인받는다. 이미 BDD 관련 도구와 프레임워크도 다수 만들어져 그 사상과 실천법과 규약 등을 소프트웨 어 개발 환경에 녹여내고 있는 모습을 보면 BDD가 발전하고 있는 것은 확실해 보인다. 그에 관해서는 8장에서 소개할 생각이다. 앞으로 좋은 테스트란 단어가 나올 때마다 댄의 깨달음을 상기하고 단어에 유념하기 바란다. 어 휘는 생각보다 중요하다. 1.4 요약 프로그래머가 마구잡이식 코딩에서 벗어난 지는 한참이 지났다. 개발자 테스트와 자동화된 테스 트는 이미 우리 일상으로 자리 잡았고, 표준화까지는 아니더라도 활발하게 논의 중인 주제임은 분명하다. 코드 전반을 보호해주는 자동화된 테스트 스위트의 가치를 더는 부정할 수 없다. 1장에서 여러분은 두 개의 고지가 무엇인지 배웠다. 이미 매우 높은 커버리지를 달성하여 테스 트를 더 만들어봐야 얻을 게 거의 없는 지점이 바로 첫 번째 고지다. 하지만 우리는 더 높이 오 를 수 있다. 테스트의 품질까지 신경 쓴다면 첫 번째 고지를 박차고 올라 더 위로 올라설 수 있 다. 전자가 테스트를 갖춰야 하는 이유라면 후자는 좋은 테스트를 갖춰야 하는 이유다. 이것이 여러분이 이 책을 산 이유고 2장 이후로 함께 도전할 과제다. 중도에서 포기하면 아무것도 얻을 게 없다. 함께 꼭 정상까지 올라가보자.
  • 42.
  • 43. 43 좋은 테스트란? CHAPTER 2 이 장의 내용 ● 무엇이 “좋은” 테스트를 만드는가? ● 테스트를 대하는 태도 ● 신뢰할 수 있는 테스트의 중요성
  • 44. 44 Part I 기반 다지기 지금 우리는 좋은 테스트에 관해 배우려 한다. 좋은 테스트를 구분하고, 좋은 테스트를 직접 만 들 것이다. 또 그저 그런 테스트라도 좋은 테스트로, 최소한 그에 근접한 모습으로 개선하는 방 법을 배울 것이다. 그렇다면 무엇이 테스트를 좋게 만드는 것일까? 어떤 비결이 숨어 있을까? 다음과 같은 고려 사항이 있다. ● 테스트 코드의 가독성과 유지보수성 ● 프로젝트 안에서, 그리고 소스 파일 안에서 코드는 적절히 구조화되어 있는가? ● 테스트가 무엇을 검사하는가? ● 테스트는 안정적이고 반복 가능한가? ● 테스트가 테스트 더블을 잘 활용하는가? 2장에서는 이 모두를 자세히 살펴볼 것이다. 아쉽게도 이 목록은 아직 완벽하지 않다. 테스트 품질에 영향을 주는 요소를 모두 나열하자면 끝도 없기 때문이다. 더구나 어떤 요소는 상황에 따라 별로 중요하지 않을 수도 있다. 예를 들 면 실행 속도가 중요한 테스트도 있는 반면 작은 기능 범위만 집중적으로 검증하는 것이 더 중 요한 테스트도 있다. 또한, 테스트 코드의 품질을 평가하는 기준도 사람마다 다르다. 코드가 좋다는 건 보통 개인 취 향에 좌우되고 나 또한 그런 개인 중 한 사람일 뿐이다. 그래서 이 책도 나의 편견과 편애에서 완전히 벗어날 수 없는 것이 현실이다. 개인 취향과는 거리를 두려고 노력했지만, 한쪽으로 치 좋은 테스트란? CHAPTER 2
  • 45. 45CHAPTER 2 좋은 테스트란? 우친 부분이 있을지도 모르겠다. 그렇다고 이게 꼭 나쁘다고 생각하진 않는다. 결국, 내가 독 자에게 줄 수 있는 최선의 가치는 그동안 훌륭한 소프트웨어 전문가들과 함께하며 경험한 코드 (특히 테스트 코드)에 관한 나의 정직한 견해일 테니 말이다. 이러한 한계를 미리 밝혀두고, 이제 테스트 품질의 여러 측면을 이야기하면서 관심 가질 만한 주제를 찾아보자. 2.1 읽기 쉬운 코드가 유지보수도 쉽다 어제 컨설팅을 마치고 사무실로 돌아와, 곧 열릴 1K 경연대회에 참가하는 동료와 대화를 나눴 다. 데모파티에서는 꽤 역사와 전통이 있는 대회로, 컴퓨터와 침낭, 에너지 음료 등을 챙겨온 해커들이 넓은 공간에 모여 주말 내내 무언가를 시합하는, 일종의 괴짜들 잔치다. 역사적인 첫 대회 때부터 해커들은 온갖 정신 나간 기술을 구사해서 어설픈 3D 애니메이션을 만들어내곤 했다. 이런 대회에서는 보통 무엇인가의 크기를 제한한다. 내 동료가 준비 중인 대회 역시 1K라는 이 름이 말해주듯 컴파일된 실행파일의 크기가 최대 1K(1,024바이트)를 넘지 말아야 한다. 이 작은 공간에 의미 있는 프로그램을 욱여넣기 위해 참가자들은 동원 가능한 모든 꼼수를 고민해 야 한다. 코드를 꽉꽉 눌러 담을 때 자주 쓰이는 꼼수 중 하나로, 서로 다른 여러 변수에 똑같은 이름을 쓰는 방법이 있다. 결과코드의 압축률이 살짝 더 높기 때문인데, 한마디로 정상적인 코 딩 기술을 겨루는 대회는 아니다. 결과코드 역시 비정상인 건 마찬가지다. 1,024바이트 안에 마구잡이로 쑤셔 넣은 소스코드는 해독 불가능한 괴물이 된다. 어떤 프로그래밍 언어를 사용했는지조차 알아보기 어렵다. 말 그 대로 쓰기 전용 코드가 만들어진다고 할 수 있다. 압축하고 욱여넣는 작업이 한 번 시작되면 무 엇을 어디서 어떻게 수정해야 하는지 구분할 수 없게 된다. 즉, 더 이상의 기능 변경은 포기한 다는 의미다. 따끈따끈한 예를 보여주고자 최근 열린 JS1K 경연대회에 실제로 제출된 소스코드를 준비해보 았다.1 자바 스크립트를 사용하여 1,024바이트 이하로 제품을 만들어내는 대회다. 1 역자주_ 다른 작품이 궁금하다면 http://js1k.com에 방문해보기 바란다.
  • 46. 46 Part I 기반 다지기 <script>with(document.body.style){margin="0px";overflow="hidden";} var w =window.innerWidth;var h =window.innerHeight;var ca =document. getElementById("c");ca.width=w;ca.height=h;var c=ca.getContext("2d"); m=Math;fs=m. sin;fc =m.cos;fm =m.max;setInterval(d,30);function p(x,y,z){ return{x:x,y:y,z:z};} function s(a,z){r =w/10;R =w/3;b =-20*fc(a*5+t); return p(w/2+(R*fc(a)+r*fs(z+2*t))/ z+fc(a)*b,h/2+(R*fs(a))/z+fs(a)*b); }function q(a,da,z,dz){var v=[s(a,z),s(a+da,z),s(a+da,z +dz),s(a,z+dz)] ;c.beginPath();c.moveTo(v[0].x,v[0].y);for(i in v)c.lineTo(v[i].x,v[i] .y);c. fill();}var Z =-0.20;var t =0;function d(){t+ =1/30.0;c.fillStyle = "#000";c. fillRect(0,0,w,h);c.fillStyle ="#f00";var n =30;var a =0;var da = 2*Math.PI/n;var dz=0.25;for(var z=Z+8;z>Z;z-=dz){for(var i=0;i<n;i++){ fog=1/(fm((z+0.7)-3,1));if(z<=2) {fog=fm(0,z/2*z/2);}var k=(205*(fog* Math.abs(fs(i/n*2*3.14+t))))>>0;k*=(0.55+0.45*fc((i/ n+0.25)*Math.PI*5) );k=k>>0;c.fillStyle="rgb("+k+","+k+","+k+")";q(a,da,z,dz);if(i%3= =0){ c. fillStyle="#000";q(a,da/10,z,dz);}a+=da;}}Z-=0.05;if(Z<=dz)Z+=dz;} </script> 그렇다. 이는 너무 극단적인 예라 일반적인 소프트웨어 회사에서 경험할 법한 상황은 아니다. 그래도 이 정도까지는 아닐지라도, 현업에서도 머리를 쥐어뜯게 하는 코드는 모두 접해봤으리 라. 그런 부류의 코드를 보통 레거시legacy, 유산라 하는데, 다른 누군가로부터 물려받아 우리가 관 리해야 하기 때문이다. 너무 난해해서 이해해보려 할 때마다 머리를 혹사해야 한다는 점에서는 조금 다르지만 말이다. 이처럼 읽기 어려운 코드는 이해하는 데만 해도 너무 많은 에너지가 소 비되기 때문에 유지보수하기가 녹록하지 않다. 그뿐만 아니라 가독성과 결함 밀도는 반비례한 다는 연구 결과도 있다.2 즉, 읽기 어려운 코드일수록 결함 수가 많다. 자동화된 테스트는 결함을 효과적으로 막아주지만, 테스트 역시 코드인지라 가독성 문제에서 벗어날 수는 없다. 읽기 어려운 코드는 검증하기도 어렵고, 결과적으로 테스트를 조금만 작성 하는 사태로까지 이어진다. 또 그렇게 작성된 테스트는 우리가 생각하는 좋은 테스트와는 거리 가 멀다. 제품의 구조와 API가 테스트를 고려하지 않고 만들어졌다면 아무리 날고 기는 테스트 작성자가 와도 결국 끔찍한 구조의 이해하기 어려운 테스트밖에 만들 수 없기 때문이다. 코드 가독성이 코드 유지보수에 지대한 영향을 끼침을 확인했다. 그렇다면 테스트 코드는 가독 성 문제에서 자유로운가? 제품 코드와는 어떻게 다른가, 아니 과연 다르긴 할까? 우선 다듬어 지지 않은 난해한 테스트 코드를 하나 살펴보자. 2 저자주_ 레이몬드 버즈(Raymond Buse), 웨스틀리 와이머(Westley Weimer) 저. 『Learning a Metric for Code Readability』. IEEE 소프트웨어 공학 분과, 2009년 11월 9일. IEEE 컴퓨터 학회 전자 도서관, http://doi.ieeecomputersociety.org/10.1109/ TSE.2009.70
  • 47. 47CHAPTER 2 좋은 테스트란? 코드 2-1 복잡하지는 않지만 가독성이 떨어지는 코드 @Test public void flatten() throws Exception { Env e = Env.getInstance(); Structure k = e.newStructure(); Structure v = e.newStructure(); //int n = 10; int n = 10000; for (int i = 0; i < n; ++i) { k.append(e.newFixnum(i)); v.append(e.newFixnum(i)); } Structure t = (Structure) k.zip(e.getCurrentContext(), new IObject[] {v}, Block.NULL_BLOCK); v = (Structure) t.flatten(e.getCurrentContext()); assertNotNull(v); } 이 테스트는 무엇을 검사하려는 것일까? 여기서 무슨 일이 벌어지고 있는지 자신 있게 이야기 할 수 있는가? 여러분이 팀의 새내기라면 이 테스트의 의도로 파악하는 데 얼마나 걸릴 것 같 은가? 만일 어느 날 갑자기 테스트가 실패하기 시작한다면 어떤 수단을 동원할 텐가? 개인적인 느낌으로는 이 코드를 살펴본 사람은 누구나 여러 가지를 뜯어고치고 싶어할 것 같다. 그리고 그러한 개선의 공통 주제는 바로 가독성일 것이다. 2.2 구조화가 잘 되어 있다면 이해하기 쉽다 영광스럽게도 소스 파일 간에 매끄럽게 이어지지 못하는 코드를 접할 기회가 여러 번 있었다. 다른 파일을 전혀 참조하지 않는 경우도 있었다. 호출되는 코드까지 소스 파일에 하나에 전부 들어 있었던 까닭이다. 소스 파일이 너무 커져서 텍스트 편집기가 감당하지 못하고 죽어버린 적도 있다. 한 번은 웹 애플리케이션이 계속 에러를 내뱉기에 원인을 살펴봤다. 자바 서버 페이 지JSP, JavaServer Pages 파일이 너무 비대해져서 컴파일된 바이트 코드의 크기가 자바 클래스파일 명 세의 허용 범위를 넘어섰다. 어이없는 경험이었다. 구조화해두면 좋다는 점뿐 아니라 제대로 구조화하지 않으면 역으로 피해를 본다는 사실도 기억해둘 필요가 있겠다.
  • 48. 48 Part I 기반 다지기 이처럼 끝나지 않는 소스는 누구도 손대고 싶어하지 않았다. 가장 간단한 개념을 수정할 때조 차 어디부터 손대야 할지 찾기 어려웠다. 기댈 수 있는 구조가 전혀 없었기 때문이다. 분할정복 divide and conquer마저 불가능하여 코드 전부를 머릿속에 집어넣고 씨름하는 것 외에 다른 도리가 없었다. [그림 2-1]에서와 같이 아무 구조나 다 코드를 이해하는 데 도움이 되는 건 아니다. 이해할 수 있는 구조가 필요한 것이다. 즉, 우리 두뇌와 사고 모델이 지지고 볶을 수 있을 정도로 정리된 구조라야 한다. 깊은 생각 없이 코드를 여러 소스 파일, 클래스, 메서드로 흩어버려도 한 번에 들여다봐야 할 코드의 양이 줄어드는 건 사실이다. 단, 당면한 주제인 프로그램 로직을 분해하 고 이해하는 데는 별다른 도움이 되지 못한다. 그래서 제대로 된 구조가 필요하다는 것이다. 그림 2-1 구조화되어 있느냐 아니냐의 단순한 문제가 아니다. 쓸모있는 구조라야 한다. 코드가 구조화 되어 있지 않다. 변경된 개념을 코드에 투영하기 어렵다. 사소한 변경이라도 악전고투를 유발한다. 아무도 손대려 하지 않는다. 코드가 좀 더 구조화된다. 하지만 우리는 손을 대야만 한다.작은 조각으로 나눈다. 하지만 쓸모있는 구조인가? 끝나지 않는 통짜 소스와 마주쳤을 때의 가장 확실한 대처법은 작은 조각으로 나누고 코드 뭉 텅이를 메서드로 뽑아내는 것이다. 500줄짜리 통짜 메서드라면 클래스 10개에 메서드 수십 개 정도로 재편할 수 있을 거다. 그렇다면 각 메서드는 평균 10줄 미만이 된다. 최소한 컴파일러 관점에서는 더 구조화된 게 확실하다. 또한, 화면을 스크롤하지 않고도 메서드 목록 전체를 살 펴볼 수 있게 된다. 하지만 코드가 도메인 모델이나 머릿속의 개념과 맞지 않아서 나눌 수 있는 명확한 경계를 찾을 수 없다면, 차라리 나누지 않느니만 못할 수도 있다. 하나의 개념이 여러 개의 물리적인 조각으 로 나뉜 꼴이 되어 여러 소스 파일을 이리저리 오가느라 시간만 더 낭비되기 때문이다. 사실은 간단한 문제다. 고수준 개념을 구현된 코드에 빠르고 정확하게 대입할 수 있는 구조면 된다. 테스트 코드는 여기에 딱 들어맞는 예다. 애플리케이션 전체를 자동화된 테스트 한 개로 보호하