2009-10-22 6 views
8

대 내가있어 여러 unittests :코드 커버리지 ExpectedException

[TestMethod()] 
[ExpectedException (typeof (ArgumentNullException))] 
public void DoStuffTest_Exception() 
{ 
    var foo = new Foo(); 
    Foo.DoStuff (null); 
} 

그것은 그 코드 커버리지가 반으로 실행 던지는 라인을 markes, 그래서 노출 된 코드의 한 블록마다 얻을 밝혀졌습니다.

잠시 동안이 문제에 대해 생각한 후에 내가 할 수있는 최선의 해결책은 try/catch를 추가하는 것이 었습니다. 이 반복되는 패턴이기 때문에, 나는 비 던지는 시험을 모든 예외 테스트를 추가 할 수있는 좋은 측면 혜택을 것

public static void ExpectException<_T> (Action action) where _T: Exception 
{ 
    try { action(); } 
    catch (_T) { return; } 
    Assert.Fail ("Expected " + _T); 
} 

이의 라인을 따라 도우미 메서드를 만들려고하고있다.

유효한 디자인입니까, 아니면 놓친 것이 있습니까?

편집 : Ugs ... 위의 ExpectException 메서드가 1 개의 차단 된 블록을 남겨 둡니다.

답변

10

제안하신 내용이 유효합니다. 당신은 코드 커버리지 문제를 제외하고, 어떤 테스트 라인이 예외를 던질 것으로 예상되는지 명시 적으로 나타 내기 때문에 ExpectedException 속성을 사용하는 것보다 낫다고 주장 할 것이다. ExpectedException을 사용하면 코드 줄이 예상되는 예외 유형을 throw 할 수 있으며 테스트가 계속 이어질 수 있습니다. 오류가 발생할 것으로 예상되지 않은 다른 호출에서 비롯된 것이라면 throw해야하는 줄이 아니기 때문에 테스트가 실패해야한다는 사실을 위장 할 수 있습니다.

당신이 제시 한 내용에 유용한 수정 잡힌 예외를 반환하는 것입니다 것입니다 무엇 : 그것을 원하는 경우

public static _T ExpectException<_T> (Action action) where _T: Exception 
{ 
    try { action(); } 
    catch (_T ex) { return ex; } 
    Assert.Fail ("Expected " + typeof(_T)); 
    return null; 
} 

이것은 (자세한 예외를 주장하는 테스트 코드를 사용 것 즉를 확인합니다. 특별한 메시지가 사용되었습니다). 당신이 제안한 것과 유사한 기본 구성을 가지고 (당신이 그것을 사용하는 것처럼 당신이 TestMethod 속성을 가지고이 보이지 않는하지만)

는 는 NUnit과는

:

Assert.Throws<ArgumentNullException>(() => Foo.DoStuff(null)) 
+0

+1. 좋은 물건. 이것은 잠시 나를 잔소리 해 왔지만 결코 고치려하지 않았습니다. – magnus

0

네, 이것은 꽤 표준 요금입니다. 우리의 많은 테스트는 똑같습니다. 동시에, 반 분기가 너무 많은 노력을 기울일만한 가치가있는 경우 코드 커버리지에 너무 높은 가치를 부여하지 않는지 궁금합니다.

+0

현재 35 %의 적용 범위에 미치지 못하기 때문에 많은 부분이 추가되지 않습니다. 이는 사소한 설계 문제 (수백 줄의 테스트 코드를 저장하는 데 발생할 수있는 문제)가 많습니다. – mafu

3

는 ExpectException하지 않는 @adrianbanks 작업 매개 변수가 예상되는 예외보다 다른 예외가 발생하는 경우 예상대로 작동 :

[TestMethod] 
public void my_test() 
{ 
    ExpectException<InvalidOperationException>(delegate() 
    { 
     throw new ArgumentException("hello"); 
    }); 
} 

을 내가 실행하면 TestMethod "my_test"난 그냥 시험 방법이 제기 System.ArgumentException되었다는 메시지 도착 : 안녕하세요. 이 경우 "Expected InvalidOperationException"이라고 표시되어야합니다.

public static void VerifierException<T>(Action action) where T : Exception 
{ 
    try 
    { 
     action(); 
    } 
    catch (Exception ex) 
    { 
     Assert.IsInstanceOfType(ex, typeof(T)); 
     return; 
    } 

    Assert.Fail("Aucune exception n'a été déclenchée alors qu'une exception du type " + typeof(T).FullName + " était attendue"); 
} 
2

나는이 오래된 주제 알아,하지만 난 같은 문제로 실행 : 나는 ExpectException 방법에 대한 새로운 버전을 제안한다.

궁극적으로 저는 스스로에게 질문했습니다. 왜 테스트의 적용 범위를 알아야합니까? 나는 그렇지 않습니다! - 그래서 그것들을 배제하겠습니다, 그래서 적용 범위는 더 깨끗합니다.

내 테스트 프로젝트에서

나는 CodeCoverage.runsettings 파일을 추가 한이 콘텐츠입니다 :

<?xml version="1.0" encoding="utf-8" ?> 
<RunSettings> 
    <DataCollectionRunSettings> 
    <DataCollectors> 
     <DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> 
     <Configuration> 
      <CodeCoverage> 
      <ModulePaths> 
       <Exclude> 
       <ModulePath>.*tests.dll</ModulePath> 
       <ModulePath>.*Tests.dll</ModulePath> 
       <!-- Add more ModulePath nodes here. --> 
       </Exclude> 
      </ModulePaths> 
      </CodeCoverage> 
     </Configuration> 
     </DataCollector> 
    </DataCollectors> 
    </DataCollectionRunSettings> 
</RunSettings> 

이 100 %이 테스트 설정 내 코드 검사는 파일

이 방법을 선택한 후 단위 테스트 코드 커버리지 시스템을 해킹 할 필요가 없습니다. :-)

+0

이 아이디어에 감사드립니다! 현재 직접 시도 할 수는 없지만 테스트 자체가 올바른지 확인하는 것은 매우 좋은 해결책 인 것 같습니다. – mafu

관련 문제