문제

이 패턴의 여러 유닛 테스트가 있습니다.

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

코드 적용 범위는 던지기 라인을 하프 런으로 표시하므로 매번 1 블록의 볼 수없는 코드를 얻습니다.

이 문제에 대해 잠시 생각 한 후, 내가 생각해 낼 수있는 최상의 솔루션은 시도/캐치를 추가하는 것이 었습니다. 이것은 반복적 인 패턴이므로 라인을 따라 도우미 방법을 만들 것입니다.

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

이것은 비 던지기 테스트에 모든 예외 테스트를 추가 할 수 있다는 좋은 부수적 이점이 있습니다.

이것은 유효한 디자인입니까, 아니면 내가 뭔가를 놓쳤습니까?

편집하다: UGS ... 위의 예상 외인 방법이 나에게 1 개의 볼 수없는 블록을 남겨 두는 것처럼 보입니다.

도움이 되었습니까?

해결책

당신이 제안하는 것은 유효합니다. 당신의 코드 커버리지 문제를 제외하고, 나는 그것이 사용하는 것보다 낫다고 주장합니다. ExpectedException 속성은 어떤 테스트 라인이 예외를 던질 것으로 예상되는지 명시 적으로 보여줍니다. 사용 ExpectedException 그것을 의미합니다 어느 테스트의 코드 라인은 예상 예외 유형을 던질 수 있으며 테스트는 여전히 전달됩니다. 오류가 던지지 않은 다른 통화에서 발생하는 경우, 던지는 줄은 그렇지 않기 때문에 테스트가 실패해야한다는 사실을 위장 할 수 있습니다.

당신이 제안한 것에 유용한 수정은 잡힌 예외를 반환하는 것입니다.

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

이를 통해 테스트 코드가 원하는 경우 예외를 더욱 주장 할 수 있습니다 (예 : 특정 메시지가 사용 되었음).

nunit (당신이 가지고있는 것처럼 사용하는 것처럼 보이지는 않지만 TestMethod 속성)은 제안한 것과 유사한 내장 구성이 있습니다.

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

다른 팁

@AdrianBanks Action 매개 변수가 예상 예외보다 다른 예외를 던지면 예상대로 작동하지 않습니다.

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

TestMethod "my_test"를 실행할 때 테스트 방법이 제기되고 System.argumentException : hello. 이 경우 "예상 된 InvalidoPerationException"이라고 표시되어야합니다. expectexception 메소드에 대한 새 버전을 제안합니다.

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");
}

나는 이것이 오래된 주제라는 것을 알고 있지만 같은 문제에 부딪쳤다.

결국 나는 나 자신에게 질문했다 : 왜 시험의 적용 범위를 알아야합니까? 나는 아니에요! - 배제하자, 커버리지가 더 깨끗합니다.

내 테스트 프로젝트에서 나는 추가했다 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%입니다.

이렇게하면 100%를 달성하기 위해 단위 테스트 코드 커버리지 시스템을 '해킹'할 필요가 없습니다.

네, 이것은 꽤 표준 요금입니다. 많은 테스트도 마찬가지입니다. 동시에, 당신은 그 반 지점의 무게가 너무 많은 노력을 기울여야한다면 코드 범위에 너무 높은 가치를 부여하지 않는지 궁금해해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top