Clean Coders 책 챕터 5 - Test Driven Development

Introduction

“처음에 그는 간단한 유닛 테스트를 먼저 적었어요. 그건 코드라고 하기에 부끄러울 정도였어요. 그 후 그는 그 테스트를 통과할 수 있는 코드를 적었어요. 그 뒤에는 아주 조금 더 테스트 코드를 적었구요, 그 다음에 다시 또 코드를 적었어요.”

“이 순환과정은 정말로 빨랐어요. 제가 익숙했던 방법으로는 첫번째 컴파일을 하기 위해서는 1~2시간은 족히 걸렸는데 말이죠. 근데 그는 매 30초마다 코드를 실행시키고 있었어요.”

“물론 뭐 Java 같은 언어로는 바로바로 실행해서 30초마다 코드를 돌릴 수 있겠죠. 근데 전 C++ 프로그래머란 말이에요? 이런 젠장-, 내 빌드는 몇분/몇시간씩 걸린단 말이에요!”

 

The Jury is in

“수술을 하는 의사는 ‘손씻기’의 중요성을 굳이 말할 필요가 없습니다. 프로그래머도 똑같아요. ‘TDD’의 중요성을 굳이 말할 필요가 없습니다.”

“당신의 코드가 어떻게 작동하는지도 모르면 어떻게 자기자신을 프로라고 칭할 수 있을까요? 테스트를 하지 않고서는 당신이 코드를 수정할 때마다 잘 작동할거라고 확신할 수 있을까요? 제대로 자동화된 테스팅 프레임워크 없이는 어떻게 코드를 수정할 때마다 바로바로 테스트 할 수 있을까요?”

 

The three laws of TDD

  1. 유닛테스트를 작성하기 전에는 어떠한 구현 코드도 작성하면 안됩니다.
  2. 이 유닛테스트를 적을 때는 딱 최소한의 ‘통과 불가능’ 상태를 만드는 테스트 코드를 적습니다. 예를 들어, ‘컴파일이 되지 않는다’도 하나의 ‘통과 불가능’ 상태입니다. 한번에 여러개의 ‘통과 불가능’ 조건을 만들면 안됩니다.
  3. 이 ‘통과 불가능’ 상태를 해결할 수 있는 최소한의 구현코드를 작성합니다. 이것보다 더 많은 구현 코드를 작성하면 안됩니다.

“이 3가지 조건이 만드는 1개의 TDD 사이클은 약 30초 정도 걸릴 것입니다.”

TDD 사이클을 계속 돌리며 개발을 진행합니다. 테스트 코드를 조금 더 추가하고, 이에 맞춰 조금 더 구현 코드를 추가합니다. 2개의 코드 흐름 - 테스트와 구현 - 이 동시에 진화하며 서로를 완성해갑니다.”

 

The Litany of Benefits

Certainty

“저 (i.e. 저자)는 Java 기반의 테스팅 도구인 FitNesse 라이브러리의 저자이자 메인테이너입니다. FitNesse는 현재 64,000줄의 코드로 작성되어있고, 그 중 28,000 줄은 약 2,200의 독립적인 유닛테스트를 위한 코드입니다. 이 테스트 코드들은 약 구현코드의 90%를 커버하고, 실행할 때는 약 90초 정도 걸립니다.”

“FitNesse 라이브러리 코드를 수정하고나면, 저는 그냥 유닛테스트를 실행해서 제 코드가 잘 작동하는지 검증합니다.”

Defect Injection Rate

“작년에 저는 20,000줄 정도의 코드를 새로 작성했습니다. 그 중 약 17개 정도의 버그가 있었어요. Safe-critical 한 용도가 아닌 프로그램으로써는 굉장히 적은 수의 버그가 검출되었습니다.”

Courage

“사람들은 왜 안좋은 코드를 보고도 고치지 않을까요? 왜냐하면 본인이 그 코드를 건들면서 프로그램이 터지는걸 걱정하기 때문입니다.”

“하지만 코드를 수정해도 프로그램이 터지지 않을 거라는 확신을 줄 수 있는 방식이 있다면, 그 사람은 자신있게 코드를 수정하지 않을까요?”

“이것이 TDD의 가장 큰 장점입니다. ‘코드를 수정하는데에 들어가는 모든 두려움’을 없앨 수 있어요.”

Documentation

“유닛테스트 내부에서는 우리가 만든 기능을 실제로 사용하면서 그 기능이 잘 작동하는지를 검증합니다. 그렇기 때문에 모든 object들은 생성되고, 그리고 해당 object에서 쓸 수 있는 기능들은 전부 테스트 됩니다.”

“그렇기 때문에 우리는 유닛테스트를 봄으로써 우리가 만든 기능들이 어떻게 사용되는지 알 수 있습니다. 마치 하나의 documentation (사용설명서) 처럼요.”

Design

“테스트를 해야한다는 조건 자체가, 개발자에게는 좋은 디자인을 고려하게 만듭니다.”

“테스트를 적고, 구현을 하고, 테스트를 적고, 구현을 하고… 테스트를 적을 때 마다, 어떻게 원하는 결과를 바로바로 만들 수 있는지 고민하면서, 자연스럽게 좋은 디자인에 대해 고려하게 됩니다.”

“‘아, 그냥 나중에 테스트 코드를 적으면 안될까?’. 안됩니다. 절대 안됩니다. 나중에 적는 테스트는 전부 ‘방어’ 목적인거에요. 구현 전에 적는 테스트는 ‘공격’입니다. 당신의 목표는 모든 공격에 대응할 수 있는 구현 코드를 작성하는 것이구요.”

 

What TDD is NOT

“TDD는 어떤 종교나 마법공식이 아닙니다.”

“TDD를 하더라도 좋지 않은 코드를 적을 수 있어요. 좋지 않은 테스트도 적을 수 있구요.”

“아주 가끔 TDD를 수행하기 어려운 상황들도 있을 겁니다. 당신이 프로라면 TDD를 사용할 때와 사용하면 안될 때를 구분할 수 있어야해요.”