Frage

Ich habe mehrere Unittests dieses Muster bekam:

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

Es stellt sich die Codeabdeckung aus markes der Wurflinie als Halb laufen, so dass ich nur 1 Block von ungedecktem Code jedes Mal.

über dieses Problem für eine Weile Nach einigem Nachdenken, ist die beste Lösung, die ich tun konnte, war das Hinzufügen einer try / catch. Da dies ein sich wiederholendes Muster, werde ich eine Hilfsmethode entlang der Linien von

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

Dies habe den schönen Nebeneffekt, dass ich alles Ausnahme-Tests auf die Nicht-Wurf Tests hinzufügen könnte.

Ist dies ein gültiges Design, oder habe ich etwas verpaßt?

Edit:. UGS ... scheint, wie die oben ExpectException Methode läßt mich mit 1 aufgedeckt Block als auch

War es hilfreich?

Lösung

Was Sie vorschlagen, ist gültig. Abgesehen von Ihnen Code-Coverage-Problem, würde ich argumentieren, es ist besser als mit dem ExpectedException Attribute, wie es ausdrücklich zeigt, welche Zeile des Tests erwartet wird, die Ausnahme zu werfen. ExpectedException Mit bedeutet, dass jede Code-Zeile in dem Test die erwartete Ausnahme Typ werfen kann, und der Test wird noch passieren. Wenn der Fehler von einem anderen Anruf stammt, die nicht zu werfen waren zu erwarten, kann es die Tatsache verschleiern, dass der Test nicht bestehen werden soll, weil die Linie, ist werfen sollte nicht.

Was für eine nützliche Modifikation wäre, was man hätte sein vorgeschlagen, die abgefangene Ausnahme zurück:

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

Dies würde den Testcode ermöglichen, um die Ausnahme geltend machen, wenn es gewünscht wird (dh. Eine bestimmte Nachricht zu überprüfen, wurde verwendet).

NUnit (obwohl es sieht nicht, wie Sie es verwenden, wie Sie ein TestMethod Attribut) hat einen eingebauten in Konstrukt ähnlich dem, was Sie vorgeschlagen haben:

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

Andere Tipps

@adrianbanks die ExpectException nicht so funktioniert erwartet, wenn der Aktionsparameter eine weitere Ausnahme als die erwartete Ausnahme auslöst:

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

Wenn ich die Testmethod execute „my_test“ Ich habe eine Meldung, dass die Testmethode angehoben und System.ArgumentException: hallo. In diesem Fall sollte es heißt „Expected InvalidOperationException“. Ich schlage vor, eine neue Version für die ExpectException Methode:

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

Ich weiß, dies ist ein altes Thema, aber ich lief in das gleiche Problem.

Schließlich fragte ich mich: Warum muss ich die Berichterstattung über die Tests wissen? Ich weiß nicht - So ist sie lassen ausschließen, so dass die Abdeckung ist sauberer

.

In meinem Testprojekt habe ich eine CodeCoverage.runsettings Datei hinzugefügt und das ist der Inhalt:

<?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>

Nach der Auswahl dieses Testeinstellungen Datei meines Code Coverage ist zu 100%

Auf diese Weise gibt es keine Notwendigkeit zu 'Hack' dem Unit-Test-Code-Coverage-System, nur um 100% zu erreichen: -)

Ja das ist ziemlich Standard-Tarif - viele unserer Tests das gleiche tun. Zur gleichen Zeit, muss man sich fragen, ob Sie nicht einen zu hohen Wert auf Code Coverage vergeben, wenn diese Halb Zweige in so viel wiegen denn es ist die Mühe wert sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top