2012-01-21 5 views
2

필자는 구현할 테스트를 고를 목록 (예 : 테스트 용 개발 예제에서 "테스트 목록")을 만들었습니다.TDD에 관한 지식이있는 구멍

Visual Studio를 시작하고 새로운 솔루션을 만들고 단위 테스트를위한 프로젝트를 추가 한 다음 선택한 클래스에 대한 테스트 방법을 지정해야합니다. 목록의.

여기 내가 막힐 곳이 있습니다. 어떤 수업이 필요한지, 어떻게 이름을 지어야하는지, 그것이 올바른지 어떻게 알 수 있는지 어떻게 알 수 있습니까? 이것은 미리 생각할 필요가있는 것입니까?

답변

0

사전에 생각해야 할 사항입니까?

사전. 이것이 테스트 주도 개발이라는 이유입니다 ...
구현하기 시작하기 전에 전에 워크 플로 을 디자인해야합니다.

+0

두 개의 학교가있는 것으로 보입니다. 하나는 프로젝트에서 비즈니스 요구 사항을 얻고, 사용자 스토리 등을 수집하고 거기에서 일하는 것처럼 준비하는 것입니다. 다른 접근법은 완전히 유기적 인 것으로 보입니다. 당신은 당신의 프로그램이하기를 원하는 검사들 외에는 아무것도 가지고 있지 않습니다. 두 번째 방법은 테스트의 컨텍스트를 생각하기가 어렵 기 때문에 차단됩니다. 예를 들어 테스트 클래스의 이름을 지정하는 방법을 모릅니다. 그러나 어쩌면 이것은 진화해야 할 필요가있는 것일 수도 있습니다. 어쩌면 나는 테스트 클래스에 약간의 이름을 주어야 할 것인가? 그리고 시간이 지남에 따라 바뀔 것인가? –

+1

@GarthMarenghi. 실제로 모든 것을 설계 한 후에 테스트를 받아야한다고 생각합니다. 그러나 구현하기 전에 테스트를해야합니다. 따라서 한 가지 접근법 만 있습니다. 거의 모든 단계를 거치지 않고 모든 응용 프로그램을 "TDD"하는 것은 어렵습니다. ** 행운을 빌어 요! ** – gdoron

3

켄트 벡 - TDD를 읽었습니까? 그것을 전부 밖으로 일하는 것을 그만 멈추십시오. 다이빙을하거나, 뭔가를하고, 효과를 발휘하고, 무엇이든지 만들어야합니다. 그렇다면 자신이해야 할 것을 더 잘 이해하고 변경할 수 있습니다. 교장 선생님이 바로 이것입니다. 어떻게하기를 원하십니까? 테스트가 원하는 것을 수행하는지 테스트를 작성한 다음 솔루션을 구현하십시오. 처음과 두 번째, 세 번째로 잘못 이해하게 될 것이지만 그 과정을 통해 실제 솔루션에 더 가깝게 다가 갈 것입니다. 작업을 마칠 때까지 귀중한 테스트 스위트와 느슨하게 커플 클래스를 사용해야합니다 끝난. REPONSE IN

편집

아니, 임의의 이름을 언급. 특정 양의 디자인을 앞에 수행해야합니다. 나는 종종 내 솔루션이 필요하다고 생각하는 핵심 유형을 생각해내는 것으로 시작한다. 그런 다음 Foo가 수행하기를 원하는 테스트를 작성하는 테스트 클래스 (Say FooTest)를 시작한다. 인터페이스를 작성하기 위해 테스트를 작성하는 프로세스를 사용합니다. 아직 존재하지 않는 유형 및 방법을 참조하고 ReSharper에서 그들을 만들 수 있습니다으로 ReSharper에서이 좋은 곳입니다 :

분명히
[TestFixture] 
public class FooTest 
{ 
    [Test] 
    public void Bar() 
    { 
     var foo = (IFoo)null; //At this point I use Resharper to create IFoo interface 

     Assert.IsTrue(foo.Bar()); //At this point I use Resharper to create bool IFoo.Bar(); 
    } 
} 

위에서와 널 심판 전 실패,하지만 난 검사를 내가 가지고있다. 메소드와의 인터페이스. 특정 구현을 개발할 준비가 될 때까지이 솔루션을 모델링하기 위해이 프로세스를 계속 수행 할 수 있습니다. 이 과정을 거치면서 유형 간의 구현이 아니라 유형 간의 상호 작용과 인터페이스에 초점을 맞 춥니 다. Foo를 구축하고 나면 위의 내용을 var foo = new Foo();으로 변경하고 모든 테스트를 녹색으로 만듭니다. 이 프로세스는 또한 단위 테스트를 작성할 때 필수적인 모든 클래스에 대한 인터페이스가 있다는 것을 의미합니다. MOQ과 같은 동적 모의 라이브러리를 사용하여 종속성을 쉽게 조롱 할 수 있습니다.

+0

네, 읽어 보았습니다. 내 수업에 임의의 이름을 부여하고 거기서부터 시작해야한다고 제안하는거야? 그게 내가 가지고있는 문제이기 때문에 나는 테스트 목록을 가지고있다.하지만 문맥은 없다. –

0

좋은 아이디어는 오히려 약간 모호한 테스트보다 도메인의 관점에서 이것에 대해 생각하기 시작하는 것입니다. 예를 들어 Foo을 개발해야합니다.이 기능은 foo1foo2입니다.

따라서 FooTest이라는 테스트 클래스를 만들고 foo1Testfoo2Test으로 만듭니다. 처음에는 이러한 테스트가 실패하고 테스트를 통과하게됩니다.

+0

두 개의 학교가있는 것처럼 보입니다. 하나는 프로젝트에서 비즈니스 요구 사항을 얻고, 사용자 스토리 등을 수집하고 거기에서 일하는 것처럼 준비하는 것입니다. 다른 접근법은 완전히 유기적 인 것처럼 보입니다. 당신은 당신의 프로그램이하기를 원하는 검사들 외에는 아무것도 가지고 있지 않습니다. 두 번째 방법은 테스트의 컨텍스트를 생각하기가 어렵 기 때문에 차단됩니다. 예를 들어 테스트 클래스의 이름을 지정하는 방법을 모릅니다. 그러나 어쩌면 이것은 진화해야 할 필요가있는 것일 수도 있습니다. 어쩌면 나는 테스트 클래스에 약간의 이름을 주어야 할 것인가? 그리고 시간이 지남에 따라 바뀔 것인가? –

0

시스템의 기능은 무엇입니까? 거기에서 시작할 수 있습니다.

주어진 계정에 대한 트랜잭션이 포함 된 문서를 읽고 차변 및 대변의 요약 요약을 생성한다고 가정 해 보겠습니다.

은의 테스트를 만들어 보자 다음 TransactionSummarizationSummary 클래스가 아직 존재하지 않는

public class TransactionSummarizationTest { 
    @Test 
    public void summarizesAnEmptyDocument() { 
     TransactionSummarization summarizer = new TransactionSummarization(); 
     Summary s = summarizer.summarizeTransactionsIn(new Scanner()); 
     assertEquals(0.00, s.debits, 0.0); 
     assertEquals(0.00, s.credits, 0.0); 
    } 

때문에, 당신은 지금을 만들 수 있습니다. 그들은과 같이 보일 것이다 : 이제 당신은 당신이 테스트를 실행할 수있는 컴파일 모든 오류 처리를 찍은 것을

TransactionSummarization.java

public class TransactionSummarization { 
    public Summary summarizeTransactionsIn(Scanner transactionList) { 
     return null; 
    } 
} 

Summary.java

public class Summary { 
    public double debits; 
    public double credits; 
} 

. summarizeTransactionsIn 메서드를 비어있는 구현으로 인해 NullPointerException으로 실패합니다. 메서드에서 요약 인스턴스를 반환하면 전달됩니다.

public Summary summarizeTransactionsIn(Scanner transactionList) { 
    return new Summary(); 
} 

테스트를 다시 실행하면 성공합니다.

이제 첫 번째 테스트가 있으니 다음 단계는 무엇입니까? 단일 트랜잭션으로 테스트를 해보고 싶습니다. 우리는 단순히 Summary에서 컴파일 오류를 수정 한 후 새 Summary

public Summary summarizeTransactionsIn(Scanner transactionList) { 
    String currentLine = transactionList.nextLine(); 
    txAmount = currentLine.split(",")[2]; 
    double amount = Double.parseDouble(txAmount); 
    return new Summary(amount); 
} 

를 반환하고 생성자 당신을 구현, 값을 축적되지 않기 때문에

@Test 
public void summarizesDebit() { 
    TransactionSummarization summarizer = new TransactionSummarization(); 
    Summary s = summarizer.summarizeTransactionsIn(new Scanner("01/01/12,DB,1.00")); 
    assertEquals(1.00, s.debits, 0.0); 
    assertEquals(0.00, s.credits, 0.0); 
} 

테스트를 실행 한 후, 우리는 실패가 나타납니다 테스트가 다시 통과해야합니다. 다음 시험은 뭐니? 우리는 무엇을 배울 수 있습니까? 글쎄요, 차변/신용에 대해 궁금 해서요. 다음에 해 봅시다.

@Test 
public void summarizesCredit() { 
    TransactionSummarization summarizer = new TransactionSummarization(); 
    Summary s = summarizer.summarizeTransactionsIn(new Scanner("01/01/12,CR,1.00")); 
    assertEquals(0.00, s.debits, 0.0); 
    assertEquals(1.00, s.credits, 0.0); 
} 

실행이 테스트, 우리는 차변이 1.00이기 때문에 그것은 실패 참조해야하지만, 학점은 0.0이다. 정확히 우리가 원했던 것의 반대이지만, 어떤 방식 으로든 트랜잭션 유형을 검사하지 않았기 때문에 완전히 예상됩니다. 이제하자.

public Summary summarizeTransactionsIn(Scanner transactionList) { 
    double debits = 0.0; 
    double credits = 0.0; 

    String currentLine = transactionList.nextLine(); 
    String[] data = currentLine.split(","); 
    double amount = Double.parseDouble(data[2]); 

    if("DB".equals(data[1])) 
     debits += amount; 

    if("CR".equals(data[1])) 
     credits += amount; 

    return new Summary(debits, credits); 
} 

이제 모든 테스트가 끝나고 다음 테스트로 넘어갈 수 있습니다. 이제 뭐? 나는이 프로젝트가 성공하기를 원한다면 파일에서 한 줄만 처리하면 우리에게 많은 도움이되지 않을 것이라고 생각합니다. 같은 시간에 여러 레코드를 처리하는 것은 어떻습니까? 시험을 치자!

@Test 
public void summarizesDebitsAndCredits() { 
    String transactions = "01/01/12,CR,1.75\\n" + 
          "01/02/12,DB,3.00\\n" + 
          "01/02/12,DB,2.50\\n" + 
          "01/02/12,CR,1.25"; 
    TransactionSummarization summarizer = new TransactionSummarization(); 
    Summary s = summarizer.summarizeTransactionsIn(new Scanner(transactions)); 
    assertEquals(5.50, s.debits, 0.0); 
    assertEquals(3.00, s.credits, 0.0); 
} 

지금, 우리의 모든 테스트 실행 우리는이 하나가 예측 가능한 방법으로 실패를 참조하십시오. 첫 번째 기록 만 처리했기 때문에 빚이 0.00이고 크레딧이 1.75라고 알려줍니다.

이제 해결해 보겠습니다. 간단한 while 루프 우리는 사업을 다시해야한다 :

public Summary summarizeTransactionsIn(Scanner transactionList) { 
    double debits = 0.0; 
    double credits = 0.0; 

    while(transactionList.hasLine()) { 
     String currentLine = transactionList.nextLine(); 
     String[] data = currentLine.split(","); 
     double amount = Double.parseDouble(data[2]); 

     if("DB".equals(data[1])) 
      debits += amount; 

     if("CR".equals(data[1])) 
      credits += amount; 
    } 
    return new Summary(debits, credits); 
} 

모든 테스트를 통과하고 내가 당신에게 나머지를 떠날거야. 예를 들어 "cr"대 "CR"과 같은 대소 문자가 혼합 된 파일이나 유효하지 않은/누락 된 데이터 등이있을 수 있습니다.

또한 나는 C#을 언급 한 모든 것을 입력 한 후에도 깨달았습니다. 불행히도 나는 자바에서 그것을했고 C#으로 변환하기에는 너무 게으르다. 그러나 나는 이것이 어쨌든 도움이되기를 바란다. :-)

고마워요!

브랜든