책소개
소프트웨어 테스트만 잘 만들어도 ‘이펙티브 개발자’ 소프트웨어 테스트는 선택이 아닌 필수다. 훌륭한 테스트는 소프트웨어 개발 프로세스 자체를 보다 효율적으로 만들어준다. 이 책에서 소개하는 실제 사례와 함께 상세히 설명된 코드 샘플을 따르다 보면 소프트웨어 테스트에 대한 체계적인 접근 방식을 알 수 있게 된다. 테스트 전문가가 오랜 연구에서 깨달은 이론과 다양한 사례를 접하면 누구나 수월하게 테스트 코드를 작성할 수 있다. 또한 단위 테스트, 통합 테스트, 시스템 테스트의 장단점부터 시작하여 테스트 주도 개발, 대규모 테스트 작성까지 소프트웨어 테스트를 실무에서 적용하는 방법을 다룬다. 테스트 유형과 각 단계를 체계적으로 살펴보고 테스트를 작성하는 일련의 과정을 자동화하고 싶다면 이 책이 큰 도움을 줄 것이다.
저자소개
전자상거래와 모바일 및 POS 결제를 돕는 네덜란드 핀테크 회사인 Tech Academy of Adyen을 이끌고 있다. 네덜란드 델프트 공과대학교 소프트웨어 공학과의 조교수로서 개발자들이 테스트와 유지 보수를 하면서 생산성을 높이는 방법을 연구 중이다. 델프트 공과대학교에서 2020년 공과대학교 교육 펠로십을 받았고, 소프트웨어 테스트 분야에서의 노력을 인정받아 2021년 ‘올해의 컴퓨터 과학 교수상’을 받았다. 브라질 상파울루 대학교에서 컴퓨터 공학 석사와 박사 학위를 취득했고, 석사 과정 동안 브라질의 이러닝 플랫폼인 알루라(Alura)를 공동 설립했다. 저자의 큰 목표는 실무자가 학문적 이론을 알게 하고, 학자가 실무에서 직면하는 도전 과제들을 이해하도록 하는 것이다. 영어로 쓴 본서 외 브라질 포르투갈어로 쓴 책으로 《Test-Driven Development(테스트 주도 개발)》, 《Orientacao a Objetos e SOLID para Ninjas(OOP와 SOLID 닌자 비급)》가 있다.
목차
옮긴이 머리말 xi베타리더 후기 xii추천사 xiv시작하며 xvii감사의 글 xix이 책에 대하여 xxii표지에 대하여 xxviCHAPTER 1 효율적이고 체계적인 소프트웨어 테스트 11.1 테스트를 하는 개발자와 하지 않는 개발자 21.2 개발자를 위한 효율적인 소프트웨어 테스트 14__1.2.1 개발 과정에서의 효율적인 테스트 15__1.2.2 반복 프로세스로서의 효율적 테스트 17__1.2.3 개발에 먼저 집중하고 나서 테스트하기 17__1.2.4 ‘제대로 된 설계’에 관한 미신 17__1.2.5 테스트 비용 18__1.2.6 효율적이면서 체계적이라는 것의 의미 18__1.2.7 테스트 자동화의 역할 191.3 소프트웨어 테스트 원칙(테스트는 왜 이렇게 어려운가) 19__1.3.1 완벽한 테스트는 불가능하다 20__1.3.2 테스트를 그만둘 때를 파악하기 20__1.3.3 가변성이 중요하다(살충제 역설) 20__1.3.4 버그는 다른 곳에 비해 많이 발생하는 지점이 있다 21__1.3.5 어떤 테스트를 하든지 결코 완벽하거나 충분하지 않다 21__1.3.6 맥락이 핵심이다 22__1.3.7 검증은 유효성 검사가 아니다 221.4 테스트 피라미드와 집중해야 할 부분 22__1.4.1 단위 테스트 23__1.4.2 통합 테스트 24__1.4.3 시스템 테스트 26__1.4.4 각 테스트 수준을 언제 사용해야 할까? 27__1.4.5 단위 테스트를 선호하는 이유 28__1.4.6 각 수준에서 무엇을 테스트해야 할까? 28__1.4.7 테스트 피라미드에 동의하지 않는다면 30__1.4.8 이 책에서 배우는 내용으로 버그를 모두 찾을 수 있을까? 321.5 연습문제 321.6 요약 35CHAPTER 2 명세 기반 테스트 372.1 요구사항이 모든 걸 말한다 38__2.1.1 1단계: 요구사항과 입출력에 대해 이해하기 41__2.1.2 2단계: 여러 입력값에 대해 프로그램이 수행하는 바를 탐색하기 41__2.1.3 3단계: 테스트 가능한 입출력과 구획을 탐색하기 43__2.1.4 4단계: 경계 분석하기 46__2.1.5 5단계: 테스트 케이스 고안하기 48__2.1.6 6단계: 테스트 케이스 자동화하기 51__2.1.7 7단계: 창의성과 경험을 발휘해서 테스트 스위트를 강화하기 532.2 간략히 살펴보는 명세 기반 테스트 552.3 명세 테스트로 버그 찾기 572.4 현업에서의 명세 테스트 67__2.4.1 프로세스는 연속적이 아니라 반복적이어야 한다 67__2.4.2 명세 테스트는 어느 정도로 수행해야 하는가? 67__2.4.3 구획인가, 경계인가? 그것은 중요하지 않다! 68__2.4.4 접점과 거점으로도 충분하지만 내점과 외점도 얼마든지 추가하자 68__2.4.5 이해를 높이기 위해 입력을 변경해서 사용하자 68__2.4.6 조합의 수가 폭발적으로 증가한다면 실용적이어야 한다 68__2.4.7 무엇을 입력할지 모르겠다면 간단한 입력을 넣어보자 69__2.4.8 관심 없는 입력에 대해 합리적인 값을 선택하자 69__2.4.9 널과 예외 케이스는 의미가 있을 때만 사용하자 69__2.4.10 테스트가 동일한 스켈레톤을 갖는 경우 매개변수화 테스트를 사용하자 70__2.4.11 요구사항은 잘게 쪼갤 수 있다 70__2.4.12 이것은 클래스와 상태에 어떻게 동작하는가? 70__2.4.13 경험과 창의성의 역할 732.5 연습문제 732.6 요약 76CHAPTER 3 구조적 테스트와 코드 커버리지 773.1 코드 커버리지, 올바른 방법 783.2 구조적 테스트 간략히 살펴보기 823.3 코드 커버리지 기준 83__3.3.1 코드 줄 커버리지 83__3.3.2 분기 커버리지 84__3.3.3 조건 + 분기 커버리지 85__3.3.4 경로 커버리지 863.4 복잡한 조건과 MC/DC 커버리지 기준 86__3.4.1 추상적인 예제 86__3.4.2 MC/DC를 달성하는 테스트 스위트 작성하기 873.5 반복문과 유사 구조 처리하기 903.6 기준 포함과 선택 913.7 명세 기반 테스트와 구조적 테스트: 실제 사례 923.8 경계 테스트와 구조적 테스트 983.9 구조적 테스트만 적용하는 것은 충분하지 않다 993.10 현업에서의 구조적 테스트 101__3.10.1 왜 사람들은 코드 커버리지를 싫어할까? 101__3.10.2 커버리지 100%가 의미하는 바는 무엇인가? 103__3.10.3 어떤 커버리지 기준을 사용할 것인가 105__3.10.4 표현식이 너무 복잡해서 단순화할 수 없다면 MC/DC를 고려하자 105__3.10.5 그 외 커버리지 기준 107__3.10.6 무엇을 수행하지 말아야 할까? 1073.11 돌연변이 테스트 1083.12 연습문제 1113.13 요약 115CHAPTER 4 계약 설계 1174.1 사전 조건과 사후 조건 118__4.1.1 단언 키워드 120__4.1.2 강한 조건과 약한 조건 1214.2 불변식 1234.3 계약 변경과 리스코프 치환 법칙 127__4.3.1 상속과 계약 1294.4 계약에 의한 설계가 테스트와 어떤 관련이 있는가? 1314.5 현업에서의 계약에 의한 설계 132__4.5.1 강한 사전 조건 vs. 약한 사전 조건 132__4.5.2 입력 유효성 검사인가, 계약인가? 아니면 둘 다인가? 133__4.5.3 단언과 예외: 둘 중 하나를 사용해야 하는 경우 135__4.5.4 예외 vs. 부드러운 반환값 136__4.5.5 계약에 의한 설계를 사용하지 않는 경우 137__4.5.6 사전 조건, 사후 조건, 불변식에 대해 테스트를 작성해야 할까? 137__4.5.7 지원 도구 1374.6 연습문제 1384.7 요약 140CHAPTER 5 속성 기반 테스트 1415.1 예제 1: 합격 등급 프로그램 1425.2 예제 2: unique 메서드 테스트 1465.3 예제 3: indexOf 메서드 테스트 1495.4 예제 4: Basket 클래스 테스트 1575.5 예제 5: 복잡한 도메인 객체 생성 1655.6 현업에서의 속성 기반 테스트 167__5.6.1 예시 기반 테스트 vs. 속성 기반 테스트 167__5.6.2 속성 기반 테스트의 일반적인 문제 168__5.6.3 창의성이 핵심이다 1695.7 연습문제 1695.8 요약 170CHAPTER 6 테스트 더블과 모의 객체 1716.1 더미, 페이크, 스텁, 모의 객체, 스파이 174__6.1.1 더미 객체 174__6.1.2 페이크 객체 174__6.1.3 스텁 174__6.1.4 모의 객체 175__6.1.5 스파이 1756.2 모의 객체 프레임워크에 대한 소개 175__6.2.1 의존성 스텁화 176__6.2.2 모의 객체와 기댓값 182__6.2.3 인수 포획 186__6.2.4 예외 시뮬레이션 1916.3 현업에서의 모의 객체 193__6.3.1 모의 객체의 단점 193__6.3.2 모의해야 하는 대상과 하지 말아야 하는 대상 195__6.3.3 날짜 및 시간 래퍼 200__6.3.4 소유하지 않은 것을 모의하기 203__6.3.5 모의에 관한 외부 의견 2056.4 연습문제 2076.5 요약 208CHAPTER 7 테스트 가능성을 위한 설계 2117.1 도메인 코드에서 인프라 코드를 분리하기 2127.2 의존성 주입과 제어 가능성 2227.3 클래스 및 메서드를 관찰 가능하게 하기 225__7.3.1 예제 1: 단언을 보조하는 메서드 도입하기 226__7.3.2 예제 2: void 메서드의 행위를 관찰하기 2277.4 의존성 전달 방법: 클래스 생성자와 메서드 매개변수 2327.5 현업에서의 테스트 가능성 설계 235__7.5.1 테스트 대상 클래스의 응집도 236__7.5.2 테스트 대상 클래스의 결합 236__7.5.3 복잡한 조건과 테스트 가능성 237__7.5.4 private 메서드와 테스트 가능성 237__7.5.5 정적 메서드, 싱글턴, 테스트 가능성 238__7.5.6 육각형 아키텍처와 설계 기법으로서의 모의 객체 238__7.5.7 테스트 가능성을 위한 설계에 대한 추가 자료 2397.6 연습문제 2397.7 요약 241CHAPTER 8 테스트 주도 개발 2438.1 첫 번째 TDD 세션 2448.2 처음 맛본 TDD에 대한 고찰 2548.3 현업에서의 TDD 255__8.3.1 TDD인가, 아닌가? 255__8.3.2 항상 TDD를 사용해야 할까? 256__8.3.3 TDD는 모든 종류의 애플리케이션과 도메인에서 동작하는가 257__8.3.4 TDD와 관련한 연구(학계에서 바라보는 TDD) 257__8.3.5 다양한 TDD 학파 259__8.3.6 TDD와 정식 테스트 2608.4 연습문제 2608.5 요약 262CHAPTER 9 대규모 테스트 작성 2639.1 대규모 테스트 사용 시기 264__9.1.1 거대 구성요소에 대한 테스트 264__9.1.2 코드 베이스 범위보다 큰 거대 구성요소 테스트 2749.2 데이터베이스와 SQL 테스트 280__9.2.1 SQL 쿼리에서 테스트해야 하는 것 281__9.2.2 SQL 쿼리에 대한 자동 테스트 283__9.2.3 SQL 테스트를 위한 인프라 설정 289__9.2.4 모범 사례 2929.3 시스템 테스트 293__9.3.1 셀레늄 294__9.3.2 페이지 객체 모델링 297__9.3.3 패턴과 모범 사례 3089.4 대규모 테스트에 대한 마지막 논의 312__9.4.1 테스트를 어느 수준으로 해야 할까? 312__9.4.2 비용/이득 분석을 수행하자 313__9.4.3 수행은 되었지만 테스트되지 않은 메서드를 조심하자 314__9.4.4 적합한 코드 인프라가 핵심이다 314__9.4.5 DSL과 테스트를 작성하는 이해 관계자를 위한 도구 314__9.4.6 다른 종류의 웹 시스템에 대한 테스트 3149.5 연습문제 3159.6 요약 316CHAPTER 10 테스트 코드 품질 31710.1 테스트 코드의 유지 보수성을 위한 원칙 318__10.1.1 테스트는 빨라야 한다 318__10.1.2 테스트는 응집력 있고 독립적이며 격리되어야 한다 318__10.1.3 테스트는 존재 이유가 있어야 한다 319__10.1.4 테스트는 반복 가능해야 하며 불안정하지 않아야 한다 319__10.1.5 테스트의 단언문은 탄탄해야 한다 321__10.1.6 테스트는 행위가 변경될 경우 깨져야 한다 321__10.1.7 테스트는 단 하나의 명확한 이유로 실패해야 한다 322__10.1.8 테스트는 작성하기 쉬워야 한다 322__10.1.9 테스트는 읽기 쉬워야 한다 322__10.1.10 테스트는 쉽게 수정하고 진화할 수 있어야 한다 32710.2 테스트 냄새 328__10.2.1 과다한 중복 328__10.2.2 불명확한 단언문 329__10.2.3 복잡하거나 외부에 있는 자원에 대한 잘못된 처리 330__10.2.4 너무 범용적인 픽스처 331__10.2.5 민감한 단언문 33110.3 연습문제 33510.4 요약 338CHAPTER 11 마무리 33911.1 비록 모델이 선형으로 보이더라도 반복이 핵심이다 33911.2 버그 없는 소프트웨어 개발: 진실 혹은 거짓? 34011.3 최종 사용자를 참여시키자 34111.4 단위 테스트는 실제로 어렵다 34111.5 모니터링에 투자하자 34311.6 더 읽을거리 343연습문제 정답 345참고문헌 354찾아보기 362