
TDD란?
TDD란 Test Driven Development의 약자로 ‘테스트 주도 개발’이라고 한다.
반복 테스트를 이용한 소프트웨어 방법론으로 작은 단위의 테스트 케이스를 작성하고 이를 통과하는 코드를 추가하는 단계를 반복하여 구현한다
TDD 특징
- 예측가능한 개발 방법이다. 끊임없이 발생할 버그에 대해 걱정하지 않고, 일이 언제 마무리될지 알 수있다.
- 코드가 가르쳐주는 모든 교훈을 학습할 기회를 갖게된다.
TDD 규칙
- 오직 자동화된 테스트가 실패할경우에만 새로운 코드를 작성한다.
- 중복을 제거한다.
TDD 행동패턴
- 매 결정사항에 대해 피드백을 제공하는 실행 가능한 코드를 기반으로 하는 유기적인 설계를 해야한다.
- 개발환경은 작은 변화에도 빠르게 반응할 수 있어야 한다.
- 테스트를 쉽게 만드려면 반드시 응집도는 높고 결합도는 낮은 컴포넌트들로 구성되게끔 설계해야한다.
TDD 프로그래밍 순서
- 빨강 - 실패하는 작은 테스트를 작성한다.
- 초록 - 빨리 테스트가 통과하게끔 만든다. 이를위해 어떤 죄악을 저질러도 좋다.
- 죄악이란 코드 복붙 혹은 함수가 무조건 특정 상수를 반환하도록 구현하는것 등을 의미
- 리팩토링 - 일단 테스틀 통과하게만 하는 와중에 생겨난 모든 중복을 제거한다.
TDD를 해야 하는 이유
용기
- 프로그래밍하면서 나타나는 두려움을 관리하는 방법이다.
- 프로그래밍의 문제가 어려울수록 각각의 테스트는 좀더 작은 부분을 커버해야 한다.
- 프로그램이 도중 내린결정과 그 결정에 대한 피드백 사이의 간격을 인지하고, 이 간격을 통제할 수 있게 해준다.
TDD 리듬
- 재빨리 테스트를 하나 추가한다. (테스트 작성)
- 모든 테스트를 실행하고 새로 추가한 것이 실패하는지 확인한다. (테스트 실행)
- 코드를 조금 바꾼다.(컴파일 되게 하기)
- 모든 테스트를 실행하고 전부 성공하는지 확인한다. (테스트 실행)
- 리팩토링을 통해 중복을 제거한다.(중복 제거)
처음 4단계는 빨리 진행해야한다. 그동안 만큼은 속도가 설계보다 더 중요하다.
하지만 설계원칙을 무시하라는 것은 아니다. 적절한 시기에 적절한 설계를. 돌아가게 만들고 올바르게 만들자.
- 처음 실패하는 코드를 빠르게 작성하면 컴파일 에러가 뜰것이다. ex) 해당 테스트의 클래스, 생성자, 메서드, 필드가 없음
- 한번에 하나씩 만들어보며 에러를 해결해보자.
중복된 로직이란?
동일한 문장이 코드의 여러장소에 나타나는것 . 중복된 로직을 하나로 끄집어내는 일엔 객체를 이용하는 것이 최고다.
중복만 제거해주면 의존성도 제거된다. → 다음 테스트를진행하기 전에 중복을 제거함으로써, 오직 한가지의 코드 수정을 통해 다음 테스트도 통과되게 만들 가능성을 최대화한다.
- 초기에는 스텁 구현을 통해 테스트를 컴파일하기도 한다.
- 돌아가는 코드에서 상수를 변수로 변경하여 점진적으로 일반화 하자.
TDD 주기
- 테스트를 작성한다. 원하는 기능의 메소드가 코드에 어떠식으로 나타나길 바라는지 생각해보고, 원하는 인터페이스를 개발하고, 올바른 답을 얻기 위해 필요한 모든 요소를 포함한다.
- 실행 가능하게 만든다. 빨리 초록 막대를 보기위해.
- 올바르게 만든다. 시스템이 작동하면, 중복을 제거하고 초록막대로 되돌리자.
TDD 주요목적
- 작동하는 깔끔한 코드를 얻는것.
- 작동하는에 해당하는 부분을 먼저 해결하고 깔끔한 코드 부분을 해결하자.
테스트를 빨리 성공하기 위한 전략
-
가짜로 구현하기
- 상수를 반환하게 만들고 진짜 코드를 얻을때 까지 단계적으로 상수를 변수로 바꾸어간다.
-
명백한 구현 사용하기
- 실제 구현을 입력한다.
-
모든일이 자연스럽게 잘 진행되고 내가 뭘 입력해야할지 알때는 명백한 구현을 사용하고 ,
도중에 빨간막대를 만나면 가짜 구현하기 방법을 사용하면서 올바른 코드로 리팩토링
값객체
- 객체를 값처럼 사용하는 패턴
- 제약사항
- 객체의 인스턴스 변수가 생성자를 통해서 일단 설정된 후에는 결코 변하지 않는다.
- 장점
- 값객체를 사용하면 별칭 문제에 대해 걱정할 필요가 없다.
- 모든 연산은 새 객체를 반환해야 한다.
큰 테스트를 공략할 수 없을 경우 진전을 나타낼 수 있는 자그마한 테스트를 만들자.
- 충분한 테스트가 없다면 지원테스트가 갖춰지지 않은 리팩토링을 만나게 될 수밖에 없다. 리팩토링을 실수했는데도 불구하고 테스트가 여전히 통과 할수있다.
- 이때는 있으면 좋을것 같은 테스트를 작성하자. 그렇게 하지 않으면 결국에는 리팩토링하다가 뭔가를 깨뜨릴 것이다.
- 리팩토링을 하기 전에 테스트를 꼭 진행하자.
하위 클래스 제거하는 방법
- 상위 클래스를 하나 만들고 이를 상속하여 공통된 코드를 상위클래스로 단계적으로 옮길수있다.
- 하위클래스에 대한 직접적인 참조가 적어진다면 하위클래스를 제거하기 위해 한단계 앞으로 나갈 수있다.
- 상위클래스에서 하위 클래스 객체를 반환하는 팩토리 메서드를 도입할 수있다.
- 하위클래스의 존재를 테스트에서 분리 함으로써 어떤 모델 코드에도 영향을 주지 않고 상속 구조를 마음대로 변경할 수 있게된다.
- 팩토리 메서드를 도입하여 테스트 코드에서 콘크리트 하위 클래스의 존재사실을 분리할 수 있다.
- 하위 클래스가 사라지면 몇몇 테스트는 불필요한 여분이된다.
- 동일한 메서드의 두 변이형 메서드 서명부를 통일 시킴으로 써 중복제거를 진행할수있다.
- 메서드 선언부를 공통상위 클래스로 옮길 수있다.
이 게시글은 Test-Driven Deveolpment By Example(켄트백 지음)도서를 참조하여 작성한 글입니다.
http://www.yes24.com/Product/Goods/12246033