2009-10-08 2 views
3

속성이있는 (많은) 클래스가 있습니다. 일부는 논리가 있고 일부 논리는 논리가 없습니다. 이러한 속성을 테스트하려고한다고 가정 할 때 어떻게해야합니까?BDD 스타일의 테스트 속성 (get/set) 단위 테스트 방법 (전략)

최근에 단위 테스트를 만들기위한 BDD 스타일에 관심이 많았습니다.

herehere을 참조하십시오.

그래서 컨텍스트의 설정을 할 것입니다 - 기본적으로 SUT를 만들고 필요한 모든 것을로드하십시오. 그런 다음 각 관찰 (테스트 방법)에서 특정 속성에 포함해야하는 내용이 포함되어 있는지 확인합니다.

여기 내 질문이 있습니다. SUT에 20 개의 속성이 있다면 20 개의 Observations/Tests를 생성합니까? 속성 중 하나에 더 흥미로운 논리가 포함되어 있다면 더 많은 것일 수 있습니다.

[Observation] 
public void should_load_FirstName() 
{ 
    Assert.Equals<string>("John", SUT.FirstName); 
} 

[Observation] 
public void should_load_LastName() 
{ 
    Assert.Equals<string>("Doe", SUT.LastName); 
} 

[Observation] 
public void should_load_FullName() 
{ 
    Assert.Equals<string>("John Doe", SUT.FullName); 
} 

단일 관찰에서 간단한 것들을 집계하면 더 좋을까요?

[Observation] 
public void should_load_properties() 
{ 
    Assert.Equals<string>("John", SUT.FirstName); 
    Assert.Equals<string>("Doe", SUT.LastName); 
    Assert.Equals<string>("John Doe", SUT.FullName); 
} 

또는 사용자 지정 특성을 사용하면 (메서드에 여러 번 적용 할 수 있음) 어떻게 될까요? 나는 가능 할 수 있도록 같은 : 일반적으로

[Observation(PropertyName="FirstName", PropertyValue="John")] 
[Observation(PropertyName="LastName", PropertyValue="Doe")] 
[Observation(PropertyName="FullName", PropertyValue="John Doe")] 
public void should_load_properties() 
{ 
} 

답변

4

당신은 시험 당 하나의 논리적 주장을 가진 후 노력해야한다. 우수한 책인 xUnit Test Patterns에는 그에 대한 좋은 토론이 포함되어 있지만 중요한 점은 테스트가 실패 할 수있는 유일한 이유가있는 경우 위반이 어디에서 발생하는지 쉽게 이해할 수 있다는 것입니다. 그래도 BDD보다 회귀 테스트와 관련이 있습니다.

이 모든 것은 모든 속성을 확인하는 단일 테스트를 작성하는 옵션이 아마도 가장 매력적이지 않음을 의미합니다. 은 모두 속성은 하나의 논리적 단언문입니다 ...

xDD (TDD, BDD, 뭐든간에)의 중심 교리는 실행 가능 사양처럼 작동해야합니다. 즉, 테스트를 할 때 즉시 확인해야합니다 무엇 테스트되고 또한 이유 예상대로입니다. 당신의 예에서 SUT.FirstName이 "Jane"이 아닌 "John"이되어야하는 이유는 분명하지 않습니다.

가능하면 하드 코딩 된 값 대신 Derived Values을 사용하도록 테스트를 작성합니다.

쓰기 가능한 속성의 경우 getter가 setter에 지정된 값을 반환하는지 단순히 확인하는 테스트를 작성합니다.

읽기 전용 속성으로, 값이 생성자 인수와 일치하는지 확인하는 테스트를 자주 작성합니다.

이러한 테스트는 일반적인 테스트 숙어를 캡슐화하는 재사용 가능한 테스트 코드로 캡슐화 할 수 있습니다. 저는 현재 library that can do just that에서 일하고 있습니다.

+0

감사의 말을 표합니다. 돌아 오는 길, CallContext의 블로그 게시물을 통해 많은 도움을 얻을 수있었습니다! Meszaros의 사이트에서 파생 된 값에 대한 링크를 읽고 그것에 대해 읽었습니다 (귀하의 후). 나는 당신이 당신의 Reverse 예제에서했던 것처럼 그것을 구현하는 극단으로 가고 싶지 않다. 변수 옆에 expectedResult를 입력 옆에 넣은 다음 리터럴 값만 사용하는 것이 좋을 것 같습니다. 필자의 경우 위의 예에서 듣기로는 분명하지 않지만 로컬 디스크에서 테스트 데이터를로드하여 SUT를 만듭니다 (수용/상호 작용 테스트 임). 입력 값을 지정하는 더 좋은 방법을 찾아야합니다 ... –

0

다른 SubSpec 구문 ([Specification] 예제)을 살펴보십시오.이 경우 끝에있는 Assert은 각각 별도의 테스트 실행을 나타냅니다.원래 람다 학대로 구문을 할인하지만 지금은 잠시 동안 그것을 사용 해왔다.