> For the complete documentation index, see [llms.txt](https://real-dev.gitbook.io/real-library/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://real-dev.gitbook.io/real-library/clean-code/readme/9..md).

# 9. 단위 테스트

<br>

#### TDD 법칙 세 가지

1. 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다.
2. 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다.
3. 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다.

이런 방식이면 돌아가는 거의 모든 코드가 테스트 될 정도로 방대한 테스트가 쌓이지만, 반대로 관리하기 어려운 문제를 유발하기도 한다.

<br>

#### 깨끗한 테스트 코드 유지하기

* 구동 코드가 변경되면 테스트 코드도 변경된다. 즉, 테스트 코드가 더러우면 구동 코드를 변경하기 어려워진다. 꼬리가 개를 흔드는 꼴로 변하는 것이다.
* 이런 상황에선 테스트 코드를 보수하고, 늘리기 어려워진다. 결국엔 기능만 돌아가면 그만이라는 생각으로 테스트 코드를 포기하게 된다.
* 문제는 테스트 코드가 없을 때 시스템의 일부를 수정하고, 다른 쪽이 멀쩡할 것이라는 확신을 가질 수가 없다는 점이다. 따라서 결함율은 점점 높아진다. 변경하면 더 손해라는 생각이 들면서 개발자는 더 이상 코드를 관리하지 않게 된다. 이거 완전 우리 상황인데…

  *결국 테스트 슈트도 없고, 얼기설기 뒤섞인 코드에, 좌절한 고객과, 테스트에 쏟아 부은 노력이 허사였다는 실망감만 남는다. 157Page*
* 따라서 테스트 코드는 실제 코드 못지 않게 중요하다. 테스트 코드는 이류 시민이 아니다. 테스트 코드는 설계와 주의가 필요하다.

<br>

#### 테스트 케이스가 없으면 실제 코드를 유연하게 만드는 버팀목도 사라진다.

* 테스트 케이스는 유연성, 유지보수성, 재사용성을 제공한다.
* **달리 말하면 테스트 케이스가 없는 상황에서 모든 변경은 잠정적인 버그다. 하 맞아요…**
* 하지만 테스트 케이스가 존재할 때 이런 공포는 사실상 사라진다. 변겨으로 인한 버그는 생기지만 어디서, 왜 생기는지 알게된다면 수정과 변경은 안전한 영역에 들어간다.

<br>

***

<br>

![Untitled](/files/9M6o42AIHoBvDA9TRtFG)

<br>

* 테스트 코드를 깨끗하게 쓰기 위해선 중복되고 중요치 않은 코드에 대해 주절하는 코드를 걷어내야한다. 또한 읽은 사람을 고려하여 구성해야한다.

<br>

***

* 테스트 코드에 적용되는 표준은 실제 코드 표준과 확실히 다르다. 간결하고, 표현력이 풍부해야 하지만, 실제 코드만큼 효율적인 필요는 없다. 실제 환경이 아니라 테스트 환경에서 돌아가는 코드이기 때문이다.
* 예를 들어, 임베디드 환경에서 동작하는 코드는 효율적이어야 한다. 컴퓨팅 사양이 한정적이기 때문이다. 반면 테스트 코드가 동작하는 환경은 그리 나쁘지 않은 상태일 가능성이 높다. 즉, 동작 코드의 표준과 테스트 코드의 표준이 둘로 나뉜다. 이런 경우라면 코드의 깨끗함을 위해 성능을 포기할 수도 있다는 얘기다. (어차피 큰 차이도 없다.)

<br>

#### F.I.R.S.T

* Fast: 테스트는 빨라야 한다. 테스트가 느리면 자주 돌릴 엄두가 나지 않고, 이러면 작업을 한참하고 테스트를 돌리게 된다. 주기적 테스트의 이점을 잃어버리는 셈이다. 코드를 마음껏 정리하지도 못한다. 결국 코드 품질이 망가지기 시작한다.
* Independent: 각 테스트는 독립적으로 동작해야 한다. 한 테스트가 다음 테스트를 수행할 준비를 하도록 구성되면 곤란하다.
* Repeatable: 테스트는 어떤 환경에서도 반복 가능해야한다.
* Self-Validating: 테스트는 자가 검증이 가능해야한다. 테스트는 성공 아니면 실패고 이게 테스트 안에서 결정되어야 한다.
* Timely: 테스트는 적시에 작성해야 한다. 단위 테스트는 테스트하려는 실제 코드를 구현하기 직전에 구현한다. 실제 코드를 구현한 다음에 테스트 코드를 작성하려고 하면 실제 코드가 테스트하기 너무 어렵다는 사실을 깨달을지도 모른다.

<br>
