# 2부. 테스트 주도 개발의 깊은 곳
###### tags: `지호`, `이규원의 현실 세상의 TDD : 안정감을 주는 코드 작성 방법`
---
## 1. 인터페이스와 구현
### 협력과 계약
- 대부분의 코드는 다른 코드와 협력
- 협렉에 필요한 것은 '어떻게'가 아닌 '무엇'
- 인터페이스
- '무엇'을 표현
- 클라이언트 코드에게 반드시 필요한 정보
- 협력하는 코드 사이의 계약
- 추상화 결과
### 정보 숨김
- 효과적인 모듈화
- 조직 간 의사소통 최소화
- 변경 여파 최소화
- 시스템 이해 도움
- 공개된 설계 결정과 숨겨진 설계 결정
- 어려운 설계 결정과 변경될 것 같은 설계 결정을 숨겨라
<br/>
## 2. 환경 변화와 적응령
### 개체 지향 (Object-oriented)
- 지연된 바인딩
- 다형성
- 일반성
### 개방-폐쇄 원칙 (Open-closed principle)
- 소프트웨어 엔터티(클래스, 모듈, 함수 등)는 확장에 열리고 수정에 닫혀야 한다.
- 상속을 염두에 둔 정의
<br/>
## 3. 입력과 출력
### 입력과 출력
- 입력 -> 논리 -> 출력
- 직접 입려과 직접 출력
- 공개된 인터페이스를 통한 입력과 출력
- 다루기 간단함
- 간접 입력과 간접 출력
- 입력된 인터페이스를 통한 입력과 출력
- 다루기 복잡함
### 부작용
- 인터페이스 설계에 드러나지 않은 출력: 반환 값 외 출력
- 자주 사용되는 부작용: 실패, 지연, 간접 출력
<br/>
## 4. 테스트 대역
### 대역과 가정
- DOC 준비 비용이 큰 경우
- 구동에 많은 자원이 필요
- 환경 제어가 어려움
- DOC가 SUT에 제공하는 계약(인터페이스)을 준수하는 대역 코드를 사용
- 대역 코드가 계약을 DOC와 동일하게 준수할 것이라고 가정
### Dummy
- SUT 준비를 위해 해결되어야 하는 의존성이 테스트 대상 논리에 의해 사용되지 않는 경우에 의존 요소를 대신하는 테스트 대역
### Stub
- 간접 입력 대역
- 미리 준비된 답을 출력
### Spy
- 간접 출력 대역
- SUT의 간접 출력을 기록
### Mock
- SUT내부의 행위(상호작용) 검증
### Facke
- 의존성 계약을 준수하는 가벼운 구현체
- DOC보다 적은 부작용
- 인메모리 데이터베이스 등
<br/>
## 5. Mockists vs Classicists
### Sociable 테스트
- 단위 테스트 -> 시스템 -> 의존 대상
### Solitary 테스트
- 단위 테스트 -> 시스템 -> 테스트 대역
### Mock의 위험
- 상태 검증 vs 행위 검증
- 정보 숨김 위배
- 테스트가 SUT 구현에 의존
- 고통스럽고 불안한 리팩토링
<br/>
## 6. Should I test private methods
### 비공개 모듈 테스트
- 비공개 모듈의 작성과 사용은 공개 모듈의 구현 영역
- 비공개 모듈 테스트는 공개 모듈 구현 노출
- 테스트가 공개 모듈 구현에 의존
- 정보 숨김 위배
- SUT와 테스트 사이의 높은 결합
<br/>
## 7. 테스트 주도 설계
### 설계가 단위 테스트에 미치는 영향
- 테스트는 인터페이스 설계에 의존
- 인터페이스 설계 품질이 낮으면 테스트 작성이 불편함
### 단위 테스트가 설계에 미치는 영향
- 테스트가 있기 때문에 리팩토링 가능
- 두려움 없이 구현 설계를 과감하게 개선
### 단위 테스트에 의지하는 인터페이스 설계
- 단위테스트
- 낮은 응집에 대한 피드백을 주지 않는다.
- 일관된 설계를 강요하지 않는다.
- 의도 노출을 요구하지 않는다.
### 단위 테스트에 의자하는 구현 설계
- 단위 테스트는 책임 분산을 유도하지 않는다.
- Mockists
- 비공개 운영 코드 테스트
<br/>
## 8. 테스트 주도 개발의 한계
### 은탄환은 없다
- 테스트 주도 개발은 유용하고 매력적인 도구
- 하지만 테스트 주도 개발 역시 남용을 주의해야 한다.
### 불안정한 목표
- 모든 코드의 목표가 안정적이지 않음
- 탐색적으로 목표를 찾아내야 한다면 테스트 코드 작성 비용 부담이 큼
### 환경 제어
- 하위 시스템이 협력하는 다른 하위 시스템, 의존성 중 일부는 출력의 예측과 제어가 어려움
- 단위 테스트는 결정적일수록 유용
- 의존성 중 일부는 동작이 매우 느림
- 단위 테스트는 빠를수록 유용
- 의존성의 단점을 보완할 대역을 도입하면 가정이 발생
- 가정으로 인한 안정감 감소
### 낮은 코드 적응력
- 코드 적응령이 낮으면 단위 테스트하기가 매우 어렵다.
- 이미 코드 적응력이 낮은 코드 기반에 테스트 주도 개발을 적용하기 어렵다.
- 코드 기반의 적응력을 높이는 것도 어렵다.
- 설계 변경의 어려움
- 변경된 설계 검증 필요
<br/>
## 9. 인터페이스와 테스트
### 인터페이스
- 한 개체가 상호작용하는 다른 개체에 제공하는 상호작용 지점
### API
- Application programming interface
- 한 시스템이 협력 시스템에 제공
- 코드 친화적 소통 수단
- 테스트 자동화 비용이 낮음
### UI
- User interface
- 한 시스템이 시스템 사용자에게 제공
- 인간 친화적 소통 수단
- 변경이 잦음
- 테스트 자동화 비용이 높음
<br/>
## 10. 인수 테스트 주도 개발
### 인수 테스트
- 배치된 코드를 대상으로 최종 클라이언트 관점으로 테스트
- UI 응용프로그램
- 사용자가 클라이언트
- 테스트 자동화 작성고 운영 비용이 상대적으로 높음
- API 응용프로그램
- 외부 시스템이 클라이언트
- 테스트 자동화 작성과 운영 비용이 상대적으로 낮음
<br/>
## 11. 코딩 계획
### 코딩 작업 설계
- 목표를 명확히 기술
- 작업 분리
### 업무 가시성
- 투명한 작업자의 업무 내용과 진행도
- 위험 요소를 더 빨리 발견할 가능성이 높아짐