TDD

TDD란

Test Driven Development, 테스트 주도 개발 : 테스트가 개발을 이끌어 나간다.

반복 테스트를 이용한 소프트웨어 방법론으로 작은 단위의 테스트 케이스를 작성하고 이를 통과하는 코드를 추가하는 단계를 반복하여 구현한다.

짧은 개발 주기의 방법에 의존하는 개발 프로세스이며, 애자일 방법론 중 하나인 eXtream Programming(XP)의 'Test-First' 개념에 기반을 둔 단순한 설계를 중요시한다.

 

eXtream Programming(XP)란?

미래에 대한 예측을 최대한 하지 않고 지속적으로 프로토 타입을 완성하는 애자일 기방법론 중 하나

이 방법론은 추가 요구사항이 생기더라도 실시간으로 반영할 수 있다.

 

단위 테스트(unit Test)란?

말 그대로 한 단위(일반적으로 class)만을 테스트하는 것이다.

 

구체적인 행동 레벨에서의 TDD 개념

테스트를 먼저 만들고 테스트를 통과하기 위한 것을 구현하는 것. 즉, 만드는 과정에서 우선 테스트를 작성하고 그걸 통과하는 코드를 만드는 것을 반복하면서 제대로 동작하는 지에 대한 피드백을 적극적으로 받는 것이다.

- 보통 SW 개발을 할 때 코딩을 다 끝나고 난 후 테스트를 한다.

- TDD 사례 (생년월일(input)을 입력 받으면 현재 나이(output)를 출력하는 프로그램)

1. 간단한 것으로 목표를 정한다. (태어난 해와 올해의 연도를 입력)

  • 2015, 2018 -> (만)3살

2. 만들기 전에 만든 후에 무엇을 테스트할 지를 설계한다.

  • 2015, 2018을 입력하면 3이 나오는 테스트 프로그램(이후 만든 프로그램을 테스트할 코드)을 만든다.

3. 이후 그 테스트를 통과할 프로그램(1.을 목표로 작성한 코드)를 만든다.

  • 올해의 연도 - 태어난 해 => 2018 - 2015

4. 테스트 프로그램으로 해당 프로그램(3.에 해당하는 코드)을 실행한다.

5. 테스트가 통과 하였다면 새로운 테스트를 추가한다.

  • input에 생월을 추가했을 때 계산하는 프로그램

 

추상적인 레벨에서의 TDD의 핵심 개념

결정과 피드백 사이의 갭에 대한 인식, 더 나아가 결정과 피드백 사이의 갭을 조절하기 위한 테크닉이라고 할 수 있다.

  • 켄트 벡(Kent Beck, 익스트림 프로그래밍의 창시자)
    • TDD란?
      • 결정과 피드백 사이의 갭에 대한 인식
      • 결정과 피드백 사이의 갭을 조절하기 위한 테크닉
    • TDD는 프로그래밍 기법이나 기술적인 느낌보다는 심리적인 것으로 볼 수 있다.
  • 결정(decision)
    • 프로그래밍을 하다보면 '이 방법으로 해야지', '이 부분은 이걸 이용해서 짜야지'라는 것을 결정한다.
  • 피드백(feedback)
    • 프로그램을 하다보면 성공/실패(에러)라는 피드백을 받는다.
  • 결정과 피드백 사이에 갭이 생긴다.
    • 갭이 커질 수록 문제이며, 그 갭을 모른다면 더욱 큰 문제이다.
    • '태어난 해와 올해의 연도를 입력'를 예시로 들었을 때,
      • 결정 : 1.을 목표로 코드를 작성할 때, '나는 빼기로 나이를 구해야겠다.'라는 것을 결정한다.
      • 피드백 : 빼기로 계산했을 때의 코드를 테스트 프로그램을 실행한 결과로, '된다'/'안된다'라는 프로그램 상의 피드백을 받는다.
      • 이 둘 사이의 갭을 인식하는 것이 TDD를 하는 것이다.

 

TDD 개발 주기

TDD 개발주기

{ Red } 단계에서는 실패하는 테스트 코드를 먼저 작성한다.

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

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

중요한 것은 실패하는 테스트 코드를 작성할 때까지 실제 코드를 작성하지 않는 것과, 실패하는 테스트를 통과할 정도의 최소 실제 코드를 작성해야하는 것이다. 이를 통해 실제 코드에 대해 기대되는 바를 보다 명확하게 정의 함으로써 불필요한 설계를 피할 수 있고, 정확한 요구 사항에 집중할 수 있다.

 

TDD의 효과

불확실성이 높을 때 '피드백'과 '협력'이 중요하다.

피드백과 협력이 중요한 이유

  • 불확실성이 높을 때 '피드백'과 '협력'을 이용하면 더 좋은 결과가 나올 확률이 높아진다.
  • TDD도 마찬가지로 '피드백'과 '협력'을 증진시키는 것이기 때문에 불확실성이 높을 때 도움이 되는 것이다.

 

일반 개발 방식과 TDD 개발 방식의 비교

일반 개발 방식

요구사항 분석 -> 설계 -> 개발 -> 테스트 -> 배포 형태의 개발 주기

이러한 방식은 소프트웨어 개발을 느리게 하는 잠재적 위험이 존재한다.

그 이유는 아래와 같다.

1. 소비자의 요구사항이 처음부터 명확하지 않을 수 있다.

2. 1.에 따라 처음부터 완벽한 설계는 어렵다.

3. 자체 버그 검출 능력 저하 또는 소스코드의 품질이 저하될 수 있다.

4. 자체 테스트 비용이 증가할 수 있다.

재설계로 인해 개발자는 코드를 삽입, 수정, 삭제하는 과정에서 불필요한 코드가 남거나 중복될 가능성이 크다.

결과적으로 코드들의 재사용이 어렵고 관리가 어려워서 유지보수를 어렵게 만든다.

작은 부분의 기능 수정에도 모든 부분을 테스트해야 하므로 전체적인 버그를 검출하기 어려워진다. 따라서 자체 버그 검출 능력이 저하된다. 그 결과 어디서 버그가 발생할지 모르기 때문에 잘못된 코드도 고치지 않으려 하는 현상이 나타나게 된다.
이 현상은 소스코드의 품질 저하와 직결된다. 작은 수정에도 모든 기능을 다시 테스트해야하는 문제가 발생하여 자체 테스트 비용이 증가된다.

 

TDD 개발 방식

일반적인 개발 방식과의 가장 큰 차이점은 테스트 코드를 작성한 뒤 실제 코드를 작성한다는 것이다.

디자인(설계) 단계에서 프로그래밍 목적을 반드시 미리 정의해야만 하고, 무엇보다 테스트해야 할지 미리 정의(테스트 케이스 작성)해야만 한다.

테스트 코드를 작성하는 도중 발생하는 예외 사항(버그 및 수정사항)은 테스트 케이스에 추가하고 설계를 개선한다.

이후 테스트가 통과된 코드만을 코드 개발 단계에서 실제 코드로 작성한다.

이러한 반복적인 단계가 진행되면서 자연스럽게 코드의 버그가 줄어들고 소스코드는 간결해진다.

또한 테스트 케이스 작성으로 인해 자연스럽게 설계가 개선됨으로 재설계 시간이 절감된다.

 

TDD를 사용해야할 상황

1. 처음 해보는 프로그램 주제 : 본인에 대한 불확실성이 높은 경우

2. 고객의 요구조건이 바뀔 수 있는 프로젝트 : 외부적인 불확실성이 높은 경우

3. 개발하는 중에 코드를 많이 바꿔야 된다고 생각하는 경우

4. 개발 이후 유지보수를 누가 해야할 지 모르는 경우

 

TDD의 효과

1. 피드백

TDD를 하면 피드백이 증가한다.

테스트를 통과하는 것으로 진행이 원활한지 자주 확인할 수 있다.

2. 협력

test를 기록함으로 이후 테스트 코드를 공유할 수 있고, 타인이 확인할 수도 있다.

이는 코드의 가독성과 이해도를 높여주며 코드의 의도가 투명하게 드러난다.

 

TDD의 장단점

 

TDD의 장점

1. 보다 튼튼한 객체 지향적인 코드 생산

TDD는 코드의 재사용 보장을 명시하므로 TDD를 통한 소프트웨어 개발 시 기능 별 철저한 모듈화가 이뤄진다.

이는 종속성과 의존성이 낮은 모듈로 조합된 소프트웨어 개발을 가능하게 하며 필요에 따라 모듈을 추가하거나 제거해도 소프트웨어 전체 구조에 영향을 미치지 않게 된다.

 

2. 재설계 시간의 단축

테스트 코드를 먼저 작성하기 때문에 개발자가 지금 무엇을 해야하는지 분명히 정의하고 개발을 시작하게 된다. 또한 테스트 시나리오를 작성하면서 다양한 예외사항에 대해 생각해 볼 수 있다. 이는 개발 진행 중 소프트웨어의 전반적인 설계가 변경되는 일을 방지할 수 있다.

 

3. 디버깅 시간의 단축

이는 유닛 테스팅을 하는 이점이기도 하다. 예를 들면 사용자의 데이터가 잘못 나온다면 DB의 문제인지, 비즈니스 레이어의 문제인지, UI의 문제인지 실제 모든 레이어들을 전부 디버깅 해야하지만, TDD의 경우 자동화된 유닛 테스팅을 전제하므로 특정 버그를 손 쉽게 찾아낼 수 있다.

 

4. 테스트 문서의 대체 가능

주로 SI 프로젝트 진행 과정에서 어떤 요소들이 테스트 되었는지 테스트 정의서를 만든다. 이것은 단순 통합 테스크문서에 지나지 않는다. 하지만 TDD를 하게 될 경우 테스팅을 자동화 시킴과 동시에 보다 정확한 테스트 근거를 산출할 수 있다.

 

5. 추가 구현의 용의함

개발이 완료된 소프트웨어에 어떤 기능을 추가할 때 가장 우려되는 점은 해당 기능이 기존 코드에 어떤 영향을 미칠지 알지 못 한다는 것이다. 하지만 TDD의 경우 자동화된 유닛 테스팅을 전제하므로 테스트 기간을 획기적으로 단축시킬 수 있다.

 

TDD의 단점

생산력 저하

처음부터 2개의 코드를 짜야하고 중간중간 테스트를 하며서 고쳐나가야하기 때문에 개발 속도가 느려진다고 생각할 수 있다.

TDD 방식의 개발 시간을 실제로 일반적인 개밥 방식에 비해 대략 10~30% 정도로 늘어난다.

 

TDD를 활용하기 어려운 이유와 잘 하는 방법

 

TDD를 하기 어려운 이유

1. 개발 시간이 증가한다.

2. 기존의 방식과 다르기에 적용하기 어렵다.

3. 'TDD는 이렇게 해야 한다'라는 이미지/틀이 있다.

  • 반드시 툴(단위 테스트 프레임워크)를 사용해야 한다라고 생각한다.
  • 규칙에 얽매여 copy&paste를 한다.

 

TDD를 잘하는 방법

적응적, 진화적으로 접근해야 한다.

백도어 접근법 : 테스트할 때 어떤 파라미터를 적용하면 내가 원하는 시스템의 시작점으로 가게 하는 것

중복적으로 하는 노력들을 조금 더 자동화하도록 업그레이드하면 발전할 수 있다.

 

TDD의 대표적인 Tool 'JUnit'

Junit이란?

Junit은 현재 전 세계적으로 갖아 널리 사용되는 'Java 단위 테스트 프레임워크'이다.

에릭 감마와 켄트 벡이 탄생시켰다. JUnit을 시작으로 CUnit(C), CPPUnit(C++), PyUnit(Python) 등 xUnit 프레임워크가 탄생하게 되었다.

 

 

출처 {

https://gmlwjd9405.github.io/2018/06/03/agile-tdd.html

https://hanamon.kr/tdd%EB%9E%80-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%A3%BC%EB%8F%84-%EA%B0%9C%EB%B0%9C/

}

'study > CS' 카테고리의 다른 글

MVC 패턴  (0) 2022.07.26

댓글