[tdd] TDD 주기의 유지

TDD 프로세스를 시작하고 나면, 그 프로세스를 매끄럽게 유지해야 한다
그 상세한 방법
시스템을 구축할 때 테스트를 작성하는 방법
테스트를 이용해 내외적인 품질 문제에 일찍 피드백을 받는 방법
테스트가 계속 변화를 뒷받침하고, 이후 개발에 걸림돌이 되지 않게 하는 방법

각 기능을 인수 테스트로 시작하라

인수 테스트는 우리가 작성하려는 기능이 아직 시스템에서 갖추지 못했다는 사실을 보여주고, 그 기능이 완성되기까지 진행 상황을 반영한다
인수테스트를 작성할때는 기반 기술(데이터베이스나 웹 서버 같은)의 용어가 아닌 응용 도메인에서 나온 용어만 이용한다.

이렇게하면 시스템에서 해야 할 일이 뭔지 이해하는데 보탬이 되고, 구현에 관한 초기 가정에 얽매이지도 않을 뿐더러 테스트가 기술적인 세부사항으로 복잡해지지도 않는다
이뿐 아니라 시스템의 기술 기반 구조가 바뀌었을 때도 인수 테스트를 보호할 수 있다

코딩을 시작하기 전에 테스트를 작성하면 달성하고자 하는 바가 명확해진다
실패하는 테스트덕에 요구사항을 충족하는데 필요한만큼의 기능을 구현하는데 집중할 수 있어 기능을 완성할 확률이 높아진다
테스트로 시작하게 되면 사용자 관점에서 시스템을 바라보게 되어 구현자 관점에서 기능을 짐작하지 않고 사용자가 필요로 하는 것을 이해하게 된다

반면 단위 테스트는 객체 집합을 격리된 상태에서 시험하므로, 그 클래스가 시스템의 나머지 부분과 조화롭게 동작할지에 대해서는 아무것도 담보하지 않는다
인수테스트는 단위 테스트를 거친 객체를 대상으로 통합 테스트를 수행할 뿐 아니라, 프로젝트를 앞으로 나아가게 한다

회귀를 포작하는 테스트와 진행상황을 측정하는 테스트를 분리하라

새 인수 테스트는 진행중인 작업을 나타내고, 기능이 준비될 때 까지는 통과하지 않을 것이다
인수 테스트를 통과하면 해당 테스트는 완료된 기능을 나타내고, 다시는 실패해서는 안된다
(실패는 이전 상태로 회귀했고, 기존 코드를 망가뜨렸음을 의미한다)

인수 테스트를 빨간색에서 녹색으로 바꾸는 활동으로 우리는 진행상태를 측정할 수 있다
정기적인 인수테스트 통과 주기는 중첩된 피드백 고리를 구동하는 엔진에 해당한다

즉 우리는 진행중인 테스트와 완료된 테스트(회귀 테스트)를 항상 분리해야 한다
만약 요구사항이 바뀐다면 거기에 영향을 받은 인수테스트를 회귀 테스트 그룹에서 빼내어서 진행중인 테스트 그룹으로 옮긴 후
새 요구사항을 반영토록 수정한 다음, 해당 테스트를 다시 통과하게끔 시스템을 변경해야 한다

테스트를 가장 간단한 성공 케이스로 시작하라

간단한지나치게 단순한으로 해석해서는 안된다
지나치게 단순한 케이스는 시스템에 가치를 별반 더하지 않으며, 더 중요한 점은 아이디어의 유효성에 관해 충분한 피드백을 전해주지 않는다는 것이다

그래서 가장 간단한 성공 케이스로 테스트를 시작해보는 것이 좋다
해당 테스트가 동작하면 솔루션의 실제 구조에 관해 더 좋은 생각이 떠오를테고, 그 과정에서 발견한 발생 가능한 실패를 처리하는 것과 이후의 성공 케이스 사이에서 우선순위를 가늠해볼 수 있다.

처리해야 할 실패 케이스, 리팩터링, 기타 작업들을 메모장 깉은 곳에 기록해두면 테스트 작성에 도움이 많이 된다

기능 구현을 할 때 실패 케이스에만 집중하면 의욕을 짐작하는데 좋지않다.
오류처리메나 신경쓰다 보면 아무것도 성취한 바가 없는 듯이 느껴지기 때문이다

읽고 싶어 할 테스트를 작성하라

각 테스트는 시스템이나 객체에서 수행할 행위로 가능한 한 명확하게 표현하는 것이 좋다

  1. 테스트를 작성하는 동안에는 테스트가 실행되지 않거나 컴파일 되지 않는다는 사실을 무시하고 테스트 내용에만 집중해서 작성하는 것이 좋다
  2. 테스트가 잘 읽히면, 이제 컴파일이나 런타임 오류를 해결한다
  3. 테스트가 명확한 오류메세지를 보이면서 예상대로 실패하면, 기반이 되는 코드를 충분히 구현했음을 의미한다
  4. 이제 테스트가 통과되도록 만들면 된다

테스트가 실패하는 것을 지켜보라