Test-Driven Development

1. TDD의 이해

XP(eXtreme Programming) 창시자 중 한 명이며, TDD를 주도한 켄트 벡은 TDD를 소개한 자신의 책에서

“프로그램을 작성하기 전에 테스트를 먼저 작성하는 것” 이라고 테스트 주도 개발을 정의했습니다.

최초에는 테스트 우선개발이라고 불렸으나 지금은 테스트 주도개발 이라고 불리고 있습니다.

TDD는 아래와 같은 차이로 이해할 수 있습니다.

“문서로 만들어 머리로 생각하고 눈으로 확인할 것인가?“

“예상 결과를 코드로 표현해놓고 해당 코드가 자동으로 판단하게 할 것인가?“


2. TDD 개발 주기

TDD에는 Clean Code 책의 유명한 소프트웨어 개발자이자 Agile 개발 선언문의 원저자 중 한 명인

Robert C Martin(“Uncle Bob”)이 제시한 세 가지 규칙이 있습니다.

  • 실패하는 테스트를 작성하기 전에는 절대로 제품 코드를 작성하지 않는다.
  • 컴실패하는 테스트 코드를 한번에 하나 이상 작성하지 않는다.
  • 현재 실패하고 있는 테스트를 통과하기에 충분한 정도를 넘어서는 제품 코드를 작성하지 않는다.
  • { Red } 단계에서는 실패하는 테스트 코드를 먼저 작성합니다.

– 코드가 어떻게 생겼는지 알 필요는 없으며 코드가 무엇을 하는지 알아야 합니다.

구현하고자 하는 기능을 다루는 테스트를 작성합니다.

  • { Green } 단계에서는 테스트 코드를 성공시키기 위한 실제 코드를 작성합니다.

– 코드의 최적화에 대해 생각하지 않고 솔루션을 찾습니다.

  • { Blue } 단계에서는 중복 코드 제거, 일반화 등의 리팩토링을 수행합니다.

– 코드를 더 잘 또는 더 효율적으로 구현하는 방법에 대해 생각합니다.


3. TDD 방법론

  • 질문

– 테스트 작성을 통해 시스템에 질문한다 (테스트 수행 결과는 실패)

  • 응답

– 테스트를 통과하는 코드를 작성해서 질문에 대답한다.

  • 정제

– 아이디어를 통합하고, 불필요한 것은 제거하고, 모호한 것은 명확히 해서 대답을 정제한다.

  • 반복

– 다음 질문을 통해 대화를 계속 진행한다.


4. TDD 작동 방식

TDD 주기에서 개발자는 기능을 정의하는 단위 테스트를 작성한 다음

이 테스트를 통과하는 코드를 작성합니다.

워크플로는 다음과 같습니다.

  1. 작은 단위 테스트를 작성한다.
  2. 빨리 테스트를 통과하기 위해 프로덕션 코드를 작성한다.
  3. 그 다음의 테스트 코드를 작성한다. 실패 테스트가 없을 경우에만 성공 테스트를 작성한다.
  4. 새로운 테스트를 통과하기 위해 프로덕션 코드를 추가 또는 수정한다.
  5. 1~4단계를 반복하여 실패/성공의 모든 테스트 케이스를 작성한다.
  6. 개발된 코드들에 대해 모든 중복을 제거하며 리팩토링한다.

자세히 알아보기 위해 TDD는 다음과 같습니다.

TDD가 어떻게 작동하는지에 대한 실용적인 예를 제공하기 위해

숫자가 10보다 작거나 같으면 “예”, 10보다 크면 “아니오”라고 말하는 목적을 가진 프로그램을 상상해 봅시다.

이 프로그램의 경우 테스트 경우는 다음과 같습니다.

  • 숫자 1을 주면 예라고 나와야 합니다.
  • 숫자 10을 주면 예라고 나와야 합니다.
  • 번호 11을 주면 안된다고 해야 합니다.
  • 번호를 1232로 지정하면 아니오라고 표시됩니다.

이러한 테스트 사례를 작성한 후 숫자가 10보다 작거나 같으면

“예”를 반환해야 함을 지정하는 코드가 작성됩니다.

그런 다음 코드는 테스트 케이스에 대해 실행되며 1과 2는 통과하고 3과 4는 실패합니다.

추가 코드가 작성되었습니다.

이번에는 숫자가 10보다 크면 “아니오”를 반환해야 함을 지정하는 코드가 작성되었습니다.

그런 다음 모든 테스트를 통과하여 모든 테스트 케이스를 다시 테스트합니다.

이제 이 모든 이미지를 코드와 함께 주석으로 설명했습니다.

리팩토링은 코드에서 이 초과 텍스트를 모두 제거하는 프로세스입니다.

그런 다음 테스트는 개별 장치의 기능을 재평가합니다.


5. TDD 유의사항

  • 테스트 케이스는 이름이 중요합니다.

작성된 테스트를 수행하거나 읽는 사람이 자신 혼자라고 은연중에 가정한다는 점이다.

그러다 보니 무엇을 테스트하는 것인지 테스트 메소드 이름만으로는 알기 어려운 경우가 종종 발생한다.

자시만 알아보기 쉽게 만들었다든가, 아니면 오해의 소지가 있는 단어를 썻기 때문이다.

보통 테스트가 실패하면 실패한 메소드의 이름이 테스트의 기준이 된다.

  • 더 이상 제대로 동작하지 않는 테스트 케이스는 제거합니다.

중본된 테스트케이스나 업무 변경등의 이유로 더 이상 제대로 동작하지 않는 테스트 케이스는 과감하게 제거한다.

  • TDD는 자동화된 테스트를 만드는 것이 최종 목표가 아닙니다.

개발의 목표 지점을 미리 정하기 위해 단위 테스트 케이스를 만들고, 목표상태 도달 여부를 빨리 확인하기 위해 단위 테스트 케이스를 자동화 시킨다.

자동화된 단위 테스트 케이스들은 TDD의 부산물이다.

개발과 설계를 위한 보조 도구이지 목적은 아니다.

  • 모든 상황에 대한 테스트 케이스를 만들 필요는 없습니다.

개발자가 개발을 하다 보면 종종 지나치게 테스트에 집착하는 경향을 보이다가 어느 순간엔가 지쳐버리는 모습을 보곤한다.

“TDD 는 힘들고 어렵고 복잡하구나”라고 말이다.

  • 여러 개의 실패하는 테스트 케이스를 한 번에 만들지 않습니다.

작성하고 있는 하나의 클래스에 대해서는 하나의 실패하는 테스트만 유지한다.

해당 실패를 성공시킨 다음에 다음 실패하는 케이스를 작성한다.

  • 하나의 테스트 케이스는 하나만 테스트하도록 작성합니다.

여러 항목을 테스트 하는 건 최대한 자제해야 한다.

  • 전통적인 테스트 기법을 배워두면 좋습니다.

각종 테스트 기법을 잘 알면 좀 더 효율적인 테스트 클래스 작성이 가능해진다.

  • 테스트 케이스는 최대한 고립시킵니다.

각각의 단위 테스트는 다른 모듈이나 시스템에 대한 독립적이고 고립된 형태로 작성 될수록 단단한 테스트 케이스가 될 수 있다.


6. TDD 장점

  • 개발의 방향을 잃지 않게 유지해줍니다.
  • 품질 높은 소프트웨어 모듈 보유하게 됩니다.
  • 자동화된 단위 테스트 케이스를 갖게 됩니다.
  • 사용설명서 & 의사소통의 수단이 됩니다..
  • 설계 개선 됩니다
  • 보다 자주 성공합니다

* TDD는 개발자가 목표를 세워 개발을 진행해나가고, 설계에 대해 지속적으로 고민할 수 있게 도와줍니다.

또한 그 와중에 정형화된 형태의 테스트 케이스들을 작성함으로써 테스트 과정을 자동화하고,

테스트의 수행 결과와 개발의 목표 달 성 여부를 즉각적으로 알수 있게 됩니다.

개발 완료 시점 이후로도 TDD의 부산물인 자동화된 단위 테스트 케이스를 이용한

지속적은 테스트가 가능해 집니다.

결과적으로 TDD는 개발에 좀 더 집중할수 있게 도와주고 프로그램의 안정성에 크게 기여합니다.


참고사이트


참고서적

  • 클린코드
  • 테스트 주도개발 TDD

Leave a Comment