TDD 테스트 주도 개발(켄트백)
-
개발자가 자기 작업의 품질에 대한 우선적 책임을 져야한다. (데밍 W.E Deming)
-
뜰에 들어서기도 전에 돌부리에 넘어지거나 다친 사람의 이야기를 듣고는 겁을 먹고 포기하지마라.
-
TDD를 쫒지말고 TDD가 자신을 따라오게 해라.
-
TDD는 과정을 하나하나 따라가면서 익혀야 된다.
-
TDD수련법
STEP-1
-
간단하고 쉬운 문제를 가지고 TDD를 시도해라.
-
RED에서 GREEN으로 가능한 빨리 바뀌도록 해라.
-
RED -> GREEN으로 가는 최대 시간을 정해 놓고 시간을 초과하면 원복하고 다시 시작해라.
-
동일한 문제를 여러번 시도 해보고 그 결과를 비교하여 동일한것과 다른것을 찾고 배움을 얻어라.
-
초기에는 리팩토링 툴을 사용하지말고 순서와 과정을 익혀라.
STEP-2
-
자신이 하는 것을 관찰하고 기록하고 분석해라.
-
프로토콜 분석(protocol analysis): 사고과정 중 생각한 것을 직접 입으로 말하도록 하면서 진행하고 이를 녹음한 것을 분석하는 것을 말한다.
-
일주일 정도의 작은 애플리케이션 하나를 오로지 TDD로 완성 해보자.
STEP-3
- TDD를 사용하지 않고 이전에 연습한 문제를 시도해보고 TDD방식과 장단점을 비교해보자.
- 세계 대학생 프로그래밍 경진대회(ICPC) 문제 등 알고리즘 중심의 문제, 자동판매기 테스터(인터랙티브 쉘(shell) 포함), 계산기, 엘레베이터 시뮬레이션, 웹 게시판, 멀티 채팅 프로그램 등을 순수하게 TDD로 풀어보고 분석해라.
-
-
개발환경은 작은 변화에도 빠르게 반응할 수 있어야 한다.
-
테스트를 쉽게 만들려면 반드시 응집도는 높고 결합도는 낮은 컴포넌트들로 구성되게끔 설계해야 한다.
-
TDD 사이클 RED -> GREEN -> Refactoring
- RED: 실패하는 작은 테스트를 작성한다.
-
GREEN: 빨리 통과하게끔 만든다. 코드를 대충 짜도된다.
-
Refactoring: 일단 테스트를 통과하게만 하는 와중에 생겨난 중복이나 불필요한 코드를 제거 한다.
-
GEEN 전략
-
가짜로 구현하기: 상수를 반환하게 만들고 진짜 코드를 얻을 때까지 단계적으로 상수를 변수로 바꾸어 나간다.
-
명백한 구현 사용하기: 실제 구현을 입력한다.
-
삼각측량(triangulation)
두 수신국이 신호를 감지하고 있을때 수신국 사이의 거리가 알려져 있고 각 수신국이 신호의 방향을 알고 있다면, 신호의 거리와 방위를 알 수 있다.
-
-
테스트 작성->컴파일->실패확인->실행하게 만듬 4단계를 빠르게 진행 후에 리팩토링을 해라.
-
테스트 코드가 제대로 작성되지 않은 상태에서 리팩토링을 시도하다가 실패하면 리팩토링에 대해 안좋은 느낌을 갖게 되고 리팩토링을 멀리하면 설계의 질이 저하된다.
-
하던 일을 중단하고 다른 일을 하는 상태에서 그 일을 또 중단하지는 않는다(짐 코플린, Jim Coplien)
-
5분이상 고민할 문제를 테스트를 돌려 컴퓨터에게 물어보면 10초 정도의 시간으로 해결될 수도 있다.
-
TDD는 확신을 주는 테스트와 정리된 코드를 통해 통찰에 대한 준비를 할 수 있다.
-
TDD가 성능 테스트, 스트레스 테스트, 사용성 테스트를 대체하진 않는다.
-
작은 단위로 작업하는 연습을 해야 한다.
-
필요한 모든 요소가 담긴 인터페이스를 개발해라.
-
깔끔하고 단순한 해법이 명백히 보인다면 그것을 입력하라.
단 입력하는데 몇분이 걸린다면 메모하고 간단하게 GEEN을 볼 수 있는 것부터 처리해라.
-
일단 먼저 작동하게 하고 깔끔하게 리펙토링해라.
-
상수를 임시로 사용하여 작동하게 한 다음 상수를 변수로 바꾸어 간다.
-
어떤 정수에 숫자를 더하면 보통 더해진 새로운 값을 갖게 될 것을 예상하지만 일반 객체는 객체 자체가 변할 수 있다.
-
객체를 값처럼 쓸 수 있는데 이것을 값 객체 패턴(value object pattern)이라고 한다.
값 객체 패턴의 특징
- 객체의 인스턴스 변수가 생성자를 통해서 설정되면 결코 변하지 않는다.
- 모든 연산은 새 객체를 반환 해야 한다.
- equals()를 구현해야 한다.
-
TDD는 완벽함을 위해 노력하지 않는다. 자신감을 가지고 전진할 수 있을 만큼의 결함의 정도를 낮추기를 희망할 뿐이다.
-
우리의 추론이 맞지 않아서 결함이 손가락 사이로 빠져나가는 수가 있다.
- 핵심 객체는 최대한 응집도는 높이고 결합도는 낮춰야 한다. 그러면 재활용하거나 이해하기 쉬운 코드가 된다.
-
테스트 사이의 커플링은 지저분한 결과를 야기한다.
-
한 번에 메서드를 하나 이상 수정하지 않으면서 테스트가 통과하게 만들 수 있는 방법을 찾으려고 노력해라.
-
setUp()에서 할당한 자원을 테스트가 끝나는 시점에 자원을 해제하는 것이 좋다.
-
문제가 하나라면 테스트도 하나만 실패해야 하고, 문제가 둘이면 테스트도 두 개만 실패해야 한다.
-
스트레스가 많으면 테스트 빈도가 적어진다.
-
테스트한다는 것은 무엇을 뜻하는가?
- 개발자가 작성한 코드가 올바르게 작동하는지 평가하는 것이다.
- 테스트는 불안함을 지루함으로 바꿔주는 효험이 있다.
-
테스트는 언제 해야하는가?
-
신규 로직을 작성하기 직전에 테스트를 작성하는 것이 좋다.
-
개발자가 로직을 변경했을 때 올바르게 작동하는지 재평가해야 한다.
-
-
테스트할 로직은 어떻게 작성해야 하나?
- 격리된 테스트를 하기 위해서 응집도는 높고 결합도는 낮은 객체의 모음으로 구성되도록한다.
- 시작하기 전에 작성해야 할 테스트 목록을 모두 적어둘 것.
- 테스트를 작성할 때 단언(assert)부터 작성하면 작업을 단순하게 만드는 강력한 효과를 볼 수 있다.
-
테스트할 데이터를 어떻게 고를 것인가?
- 데이터 값을 산발하지 마라. 1과 2 사이에 개념적 차이점이 없다면 1을 사용해라.
- 세 항목만으로 동일한 설계와 구현을 이끌어낼 수 있다면 굳이 열 개나 되는 항목을 나열할 필요는 없다.
- 여러 의미를 담는 동일한 상수를 쓰지 않아야 한다.
-
테스트 자체에 예상되는 값과 실제 값을 포함하고 이 둘 사이의 관계를 드러내기 위해 노력해라.
-
테스트를 작성할 때는 컴퓨터뿐 아니라 후에 코드를 읽을 다른 사람도 생각해야 한다.
-
테스트 작성에서는 명백한 데이터를 사용함으로서 개발자의 의도를 좀 더 전달할 수 있다.
-
명백한 데이터 사용은 코드에 매직넘버를 쓰지 말라는 것에 대한 예외적인 규칙일 수 있지만, 이미 정의된 상수가 있다면 그것을 사용해라.
-
주제와 무관한 아이디어가 떠오르면 이에 대한 테스트를 할일 목록에 적어놓고 다시 주제로 돌아올 것.
-
시스템 장애가 보고 되면 그 장애로 인하여 실패하는 테스트를 작성해라.
-
시스템 장애를 손쉽게 격리시킬 수 없다면 리팩토링해야 한다.
-
키보드로 뭘 쳐야 할지 알면 명백한 구현을 한다. 잘 모르겠다면 가짜 구현을 한다. 올바른 설계가 명확하지 않다면 삼각측량 기법을 사용한다. 그래도 모르겠다면 샤워나 하러 가는 거다.
-
셀프 션트: 자기가 보낸 것이 다시 자신에게 제대로 돌아오는지 확인하는 루프백 테스트와 유사함.
-
크래시 테스트 더미: 예외 상황을 테스트하기 위해 예외를 던지는 메서드를 작성하고 호출하여 테스트 하는 방법.
-
혼자 프로그래밍을 할 때 마지막 테스트를 깨진 상태로 끝마치면 다시 시작할 때 작업의 시작점을 명확히 알 수 있어서 좋다.
-
팀 프로그래밍을 할 때는 모든 테스트가 성공한 상태로 끝마치는 것이 좋다.
-
테스트를 통과시키기 위해 주석 처리하는 것은 엄격히 금지된다.
-
어떻게 구현해야 될지 확신이 드는 것은 명백한 구현을 하고, 예매하거나 잘 모르겠으면 가짜 구현이나 삼각측량을 사용하고 작은 단위로 테스트를 해라.
-
모든 것을 명백한 구현만 사용하면 자신에게 완벽함을 요구하게 된다. 이것은 자신을 힘들게 만들 수 있다.
-
단언(assert)란 어떤 조건이 참인지 아닌지 검사하는 메서드.
-
특정 객체들을 setUp해놓고 여러 테스트에서 사용하는데 이때 특정 객체들을 테스트 픽스처라고 부른다.
-
@BeforeEach에서 외부 리소스(파일 등)을 할당했다면 @AfterEach에서 반드시 해제해야 한다.
댓글남기기