2011-11-02 2 views
5

TDD에 관한 수많은 스크린 캐스트를 읽은 적이 있지만 아직 실제 프로젝트에서 사용하는 데 어려움을 겪고 있습니다. 내 주요 문제는 어디에서 시작할 것인지, 어떤 테스트가 첫 번째 테스트가되어야하는지 모른다는 것입니다. 외부 시스템의 메소드 (예 : 통지)를 호출하는 클라이언트 라이브러리를 작성해야한다고 가정합니다. 실제 프로젝트에서 TDD 시작점을 선택하는 방법은 무엇입니까?

NotificationClient client = new NotificationClient("abcd1234"); // client ID 
Response code = client.notifyOnEvent(Event.LIMIT_REACHED, 100); // some params of call 

이 장면 뒤에 일부 번역 및 메시지 형식으로 준비가 다음 그래서 나는 내 클라이언트 응용 프로그램에서 그것을 숨기려 나는이 클라이언트가 작동합니다.

어디에서 어떻게 시작해야할지 모르겠다. 이 라이브러리에 대해 거친 클래스를 설정해야합니까? 그래서, 이러한 테스트와 내가 TDD 상태로 아무 아기 단계, 한 번에 전체 작업의 구현을 작성하도록 강요하고있어 경우 나는

public void testClientSendInvalidEventCommand() { 
    NotificationClient client = new NotificationClient(...); 
    Response code = client.notifyOnEvent(Event.WRONG_EVENT); 
    assertEquals(1223, code.codeValue()); 
} 

다음과 같이 테스트 NotificationClient로 시작해야합니다. 나는 클라이언트에서 sosmething을 조롱 할 수 있지만, 나는이 일을 미리 조롱해야한다는 것을 알아야한다. 그래서 나는 만들어 질 수있는 선행을해야한다.

아마도 맨 아래부터 시작하여이 메시지 서식 지정 구성 요소를 먼저 테스트 한 다음 올바른 클라이언트 테스트에 사용해야합니까?

올바른 방법은 어떤 방법입니까? 우리는 항상 위에서부터 시작해야합니까 (이 거대한 단계를 처리하는 방법)? 원하는 기능의 작은 부분을 구현하는 모든 클래스 (이 예에서는 Formatter)부터 시작할 수 있습니까?

내 테스트를 어디서 치는지 알아야한다면 더 쉽게 진행할 수 있습니다.

답변

1

응용 프로그램의 각 끝 부분에 후크 acceptance tests을 혼동하고 unit testsexecutable specifications을 형성하지 마십시오.

'순수한'TDD를 수행하는 경우 구현을 유도하는 단위 테스트를 유도하는 수용 테스트를 작성합니다. testClientSendInvalidEventCommand이 수락 테스트이지만, 복잡한 일에 따라 구현을 여러 클래스에 위임하게됩니다. 단원 단위 테스트를 개별적으로 수행 할 수 있습니다.

복잡한 문제를 테스트하고 이해하기 위해 복잡한 문제가 발생하기 전에 테스트 구동이라고하는 이유는 디자인입니다.

+0

그러나 이러한 클래스를 찾아 단위 테스트를 작성하고 시작하는 위치를 찾는 방법은 무엇입니까? 나는 TDD를위한 출발점을 선택할 수 있도록 몇몇 수업을 미리 준비해야한다고 생각합니다. 그렇다면이 지점이 어디에 있어야할까요? 그것이 시스템의 가장자리에 있어야 하는가, 아니면 시스템의 중간에있을 수 있는가? –

+0

TDD 상향식 또는 하향식 방식을 사용할 수 있습니다. 나는 당신의 예제에 Formatter가 어떻게 맞는지 보지 못했다. 테스트를 통과하면 ** 통과해야하는 ** 최소 ** 코드 금액을 작성해야합니다. –

0

TDD의 한 가지 목표는 테스트가 디자인에 정보를 제공한다는 것입니다. 그래서 당신이 당신의 NotificationClient을 구현하는 방법에 대해 생각할 필요가 있다는 사실은 좋은 것입니다; 그것은 (희망적으로) 단순한 추상화를 생각하게 만듭니다.

또한 TDD 정렬은 상수 리팩토링을 가정합니다. 아마 첫 번째 해결책은 마지막이 아닐 것이다. 따라서 코드를 다듬어 가면서 컴파일 오류에서 실제 런타임 문제에 이르기까지 무엇이 문제인지 알려주는 테스트가 제공됩니다.

그래서 나는 바로 들어가서 제안한 테스트부터 시작하겠다. 모의 객체를 만들 때 조롱하는 객체의 실제 구현을위한 테스트를 만들어야합니다. 일을 이해하고 리팩토링해야 할 필요가 있으므로, 테스트를 수정해야합니다. 그것이 작동하도록되어있는 방법입니다 ...

+0

자, 필자는 여기에 두 명의 공동 작업자, 즉 필요한 형식으로 메시지를 만들기위한 Formatter와 연결을 처리하고 하위 메시지를 보내는 ConnectionHandler를 확인했다고 가정합니다. 테스트를 시작하는 것으로 충분합니까? 어디서부터 시작해야할까요? ConnectionHandler 또는 Formatter를 테스트 할 때? 아니면 두 명의 deps가있는 클라이언트가 조롱을 당했을까요? –

+0

그냥 하나 또는 다른 것을 선택하십시오 - 나는 당신이 분석 마비 상태에 있다고 생각합니다 - 그냥 해보면 스스로 작동합니다 ... – hvgotcodes

1

테스트가 아래에서 위로 또는 아래에서 위로 디자인을 이동하도록 선택할 수 있습니다. 둘 다 서로 다른 상황에서 서로 다른 개발자에게 적합합니다.어느 쪽의 접근 방식이든 "선행 (upfront)"디자인 결정을 내릴 수밖에 없지만 좋은 방법입니다. 테스트를 작성하기 위해 이러한 결정을 내리는 것은 테스트 중심 디자인입니다!

귀하의 경우에는 개발하려는 시스템에 대한 높은 수준의 외부 인터페이스가 있어야합니다. 노 티피 케이션 클라이언트의 사용자가이 노 트와 상호 작용하여 실패하게하는 방법에 대한 테스트를 작성하십시오. 이 테스트는 수락 또는 통합 테스트의 기초이며 설명하는 기능이 완료 될 때까지 계속 실패 할 것입니다. 괜찮아. 이제 한 단계 아래로 내려갑니다. 고급 인터페이스를 제공하기 위해 필요한 단계는 무엇입니까? 이러한 단계에 대한 통합 또는 단위 테스트를 작성할 수 있습니까? 사용자가 고려하지 않은 종속성이있어 정의하기 시작한 알림 센터 인터페이스를 변경하게 할 수 있습니까? 실제로 단위 테스트에 도달했음을 알 때까지 실패한 테스트로 깊이 우선 정의 동작을 드릴 다운합니다. 이제 단위 테스트를 통과하고 계속 진행하십시오. 통합 테스트를 통과하기에 충분할 때까지 단위 테스트를 통과하십시오. 결국에는 테스트 트리를 심층적으로 작성한 후 테스트를 통해 설계가 잘 수행 된 기능을 테스트해야합니다.

2

나는이 선으로 시작 했죠 : 우리는 클라이언트 ID를 필요로하는 NotificationClient가 필요 같은

NotificationClient client = new NotificationClient("abcd1234"); // client ID 

는 소리. 그것은 테스트하기 쉬운 것입니다. 내 첫 번째 테스트 같은 것을 볼 수 있습니다 물론

public void testNewClientAbcd1234HasClientId() { 
    NotificationClient client = new NotificationClient("abcd1234"); 
    assertEquals("abcd1234", client.clientId()); 
} 

를, 그것은 처음에 컴파일되지 않습니다 - 나는 문자열 매개 변수와 클라이언트 ID() 메소드를 사용하는 생성자와 NotificationClient 클래스를 작성했던하지 때까지 문자열을 반환하지만 TDD주기의 일부입니다. (나는 빈 문자열로 하드 코딩 된 ClientID()의 반환을했습니다 때문에)이 시점에서

public class NotificationClient { 
    public NotificationClient(string clientId) { 
    } 
    public string clientId() { 
     return ""; 
    } 
} 

, 내 테스트를 실행하고 실패 할 볼 수 있습니다.
public string clientId() { 
     return "abcd1234"; 
    } 

지금 내 모든 테스트를 통과, 그래서 나는 다음에 무엇을 고려할 수 있습니다 : 내 실패 단위 테스트를했으면, 나는 통과 테스트를 얻기 위해 ( NotificationClient에) 충분한 생산 코드를 작성합니다.

public void testNewClientBcde2345HasClientId() { 
    NotificationClient client = new NotificationClient("bcde2345"); 
    assertEquals("bcde2345", client.clientId()); 
} 

내 테스트 스위트를 실행하고 testNewClientBcde2345HasClientId()가 실패 관찰 : 다음 단계 (에 분명 잘) 명백한 내가 누구의 ID "ABCD1234"없는 클라이언트를 만들 수 있는지 확인하는 것입니다 그 내 모든 테스트를 통과 할거야,에 몰래 아니오 인쇄상의 오류가 없다고 가정

public class NotificationClient { 
    private string _clientId; 
    public NotificationClient(string clientId) { 
     _clientId = clientId; 
    } 
    public string clientId() { 
     return _clientId; 
    } 
} 

및 I : testNewClientAbcd1234HasClientId()를 통과하면서, 지금은 NotificationClient에 멤버 변수를 추가하는 좋은 이유가있어 다음 단계가 무엇이든간에 앞으로 나아갈 수 있습니다. 귀하의 예에서는 아마도 notifyOnEvent(Event.WRONG_EVENT)이 이고 그 중 codeValue()은 1223이 반환된다는 것을 테스트했을 것입니다.

이러한 정보는 도움이 될 수 있습니까?

관련 문제