- Test Driven Development
- 테스트 주도 개발 : 테스트가 개발을 이끌어 나간다.
테스트를 먼저 만들고 테스트를 통과하기 위한 것을 짜는 것 즉, 만드는 과정에서 우선 테스트를 작성하고 그걸 통과하는 코드를 만들고를 반복하면서 제대로 동작하는지에 대한 피드백을 적극적으로 받는 것이다.
- 보통은 sw개발을 할 때 코딩을 다 끝나고 난 후 테스트를 한다.
- 코딩이 끝난 후 : 개발자가 코딩을 다 짜고 난 후 완성했다고 생각할 때
- 이것의 순서를 바꾸는 것이 TDD를 적용하는 것이다.
- TDD를 적용한 사례
- 예를 들어, 생년월일(input)을 입력받으면 현재 나이(output)를 출력하는 프로그램
- 처음에는 간단하는 것을 목표로 정한다. (태어난 해와 올해의 연도 입력)
- 2015, 2018 -> (만)3살 우선 이것을 만들겠다는 생각을 한다.
- 만들기도 전에 만든 후 무엇을 테스트할지를 설계한다.
- 2015, 2018를 입력하면 2가 나오는 테스트 프로그램(장차 만들 프로그램을 테스트할 코드)를 만든다.
- 그 다음에 그 테스트를 통과할 프로그램을 만든다.
- 올해의 연도 - 태어난 해
- 2018 ~ 2015
- 테스트 프로그램으로(3. 에 해당하는 코드) 프로그램을 실행한다.
- 통과했으면 새로운 테스트를 추가한다.
- 이번에는 생월을 추가했을 때 계산하는 프로그램
- 위와 같은 작업을 계속 한다.
결정과 피드백 사이의 갭에 대한 인식
, 더 나아가 결정과 피드백 사이의 갭을 조절하기 위한 테크닉
이라고도 할 수 있다.
- 켄트 백(Kent Beck, 익스트림 프로그래밍의 창시자)
- TDD란?
- 결정과 피드백 사이의 갭에 대한 인식
- 결정과 피드백 사이의 갭을 조절하기 위한 테크닉
- TDD는 프로그래밍 기법이나 기술적인 느낌보다는 심리적인 것으로 볼 수 있다.
- TDD란?
- 결정 (decision)
- 프로그램을 하다보면 '이 방법으로 해야지' , '이 부분은 이걸 이용해서 짜야지' 라는 것을 결정한다.
- 피드백 (feedback)
- 프로그램을 하다보면 성공/실패(에러)라는 피드백을 받는다.
- 이 둘(결정과 피드백) 사이에 갭이 생긴다
- 갭이 커질수록 문제
- 내가 그 갭을 모르면 더 큰 문제
- 즉, 위의 예와 함께 설명하자면
- 결정: 1. 을 목표로 코드를 작성할 때, '나는 빼기로 나이를 구해야겠다' 라는 것을 결정한다.
- 피드백 : 빼기로 계산했을 때의 코드를 테스트 프로그램을 실행한 결과로, 된다/안된다라는 프로그램 상의 피드백을 받는다.
- 이 둘 사이의 갭을 내가 인식한다면 TDD를 하고 있는 것이다.
불확실성이 높을 때 피드백
과 협력
이 중요하다.
- 피드백과 협력이 중요한 이유
- 불확실성이 높을 때 피드백과 협력을 이용하면 더 좋은 결과가 나올 확률이 높아진다.
- TDD도 마찬가지로 피드백과 협력을 증진시키는 것이기 때문에 불확실성이 높을 때 도움되는 것이다.
- 어떤 부분에 대해 코딩을 여러번 해봤고 결과가 뻔하다면 TDD를 하지 않아도 된다.
- 또한 TDD를 했을 때 얻는 것이 적다면 TDD를 하지 않아도 된다.
- 그렇다면 TDD는 어떤 상황에서 해야할까?
- 처음해보는 프로그램 주제
- 나에 대한 불확실성이 높은 경우
- 고객의 요구조건이 바뀔수 있는 프로젝트
- 외부적인 불확실성이 높은 경우
- 개발하는 중에 코드를 많이 바꿔야 된다고 생각하는 경우
- 내가 개발하고 나서 이 코드를 누가 유지보수할지 모르는 경우
- 즉, 불확실성이 높을 때 TDD를 하면 된다.
모든 애자일의 실천법은 피드백과 협력을 동시에 증진시킨다.
- 피드백
- TDD를 하면 피드백이 증가한다.
- 테스트를 통과하는 것으로 잘되고 있는가를 자주 확인할 수 있다.
- 이 부분은 사람들이 쉽게 느낄 수 있다.
- 협력
- 테스트코드를 남들에게 보여줄 수 있고 남들은 그 코드를 직접 실행해볼 수 있다.
- 공유하면 협력이 증진된다.
- 남이 짠 코드를 빨리 이해가능
- 남이 짠 코드를 쉽게 이해가능
- 용기가 생긴다.
- 보다 튼튼한 객체 지향적인 코드 생산
TDD는 코드의 재사용 보장을 명시하므로 TDD를 통한 소프트웨어 개발 시 기능 별 철저한 모듈화가 이뤄진다.
이는 종속성과 의존성이 낮은 모듈로 조합된 소프트웨어 개발을 가능하게 하며 필요에 따라 모듈을 추가하거나 제거해도 소프트웨어 전체 구조에 영향을 미치지 않게 된다.
-
재설계 시간의 단축 테스트 코드를 먼저 작성하기 때문에 개발자가 지금 무엇을 해야하는지 분명히 정의하고 개발을 시작하게된다. 또한 테스트 시나리오를 작성하면서 다양한 예외사항에 대해 생각해 볼 수 있다. 이는 개발 진행중 소프트웨어의 전반적인 설계가 변경되는 일을 방지할 수 있다.
-
디버깅 시간의 단축
이는 유닛 테스팅을 하는 이점이기도 하다. 예를 들면 사용자의 데이터가 잘못 나온다면 db의 문제인지, 비즈니스 레이이어의 문제인지 UI의 문제인지 실제 모든 레이어들을 전부 디버깅 해야하지만, TDD의 경우 자동화 된 유닛 테스팅을 전제하므로 특정 버그를 손 쉽게 찾아낼 수 있다.
- 테스트 문서의 대체 가능
주로 SI 프로젝트 진행 과정에서 어떤 요소들이 테스트 되었는지 테스트 정의서를 만든다. 이것은 단순 통합 테스트문서에 지나지 않는다. 하지만 TDD를 하게 될 경우 테스팅을 자동화 시킴과 동시에 보다 정확한 테스트 근거를 산출할 수 있다.
- 추가 구현의 용의함
개발이 완료된 소프트웨어에 어떤 기능을 추가할 때 가장 우려되는 점은 해당 기능이 기존 코드에 어떤 영향을 미칠지 알지 못한다는 것이다. 하지만 TDD 의 경우 자동화된 유닛 테스팅을 전제하므로 테스트 기간을 획기적으로 단축시킬 수 있다
이러한 TDD 장점에도 불구하고 모두가 이 개발 프로세스를 따르는 것은 아니다. 그이유는 ?
가장 큰 단점은 바로 생산성 저하이다.
- 개발 속도가 느려진다고 생각하는 사람이 많기 때문에 TDD에 대해 반신반의 한다.
- 왜냐하면 처음부터 2개의 코드를 짜야하고 중간중간 테스트를 하면서 고쳐나가야하기 때문이다.
- TDD 방식의 개발 시간은 일반적으로 개발 방식에 비해 대략 10% ~ 30% 정도로 늘어난다.
- SI 프로젝트에서는 소프트웨어의 품질보다는 납기일 준수가 훨씬 중요하기 때문에 TDD 방식을 잘 사용하지 않는다.
몸에 체득한 것이 많을수록 바꾸기 어렵다.
오히려 개발을 별로 해보지 않은 사람들에겐 적용하기 쉽다.
- 반드시 툴(단위 테스트 프레임워크)을 써서 개발해야 된다. 라고 생각한다.
- 이러한 규칙에 얽매이는 것은 애자일 방식이 아니다.
- 결국엔 규칙에 얽매여 똑같은 테스트를 copy&paste한다.
- 도구/규칙에 집착하다 보니 TDD가 어려워지는 것이다.
계속해서 본인이 일하는 방식을 업그레이드 해야 한다.
예를 들어 게임을 개발하면서 stage 3를 테스트 할 때,
항상 stage1 , 2를 클리어한 뒤 테스트를 해야한다
-> 테스트 비용 증가
이럴 때에 어떻게 하면 비용을 낮출 수 있을까를 고민
-> 바로 stage3으로 갈 수 있도록 만든다.
피드백을 좀 더 저렴하게 자주 받을 수 있다.
Back Door 접근법 : 테스트를 할 때 파라미터를 적용하여 본인이 원하는 시스템의 시작점으로 가게하는 것.
즉, 중복적으로 하는 노력들을 자동화하도록 업그레이드하면 발전할 수 있다.