2010-07-23 10 views
7

Ich arbeite gerade an einigen Testfällen, und ich stelle regelmäßig fest, dass ich in jedem Fall mit mehreren Behauptungen enden werde. Zum Beispiel (über vereinfachte und Kommentare der Kürze halbe gestrippt):Wie verhindert man "Überprüfungen" in einem Testfall? (C#/nUnit)

[Test] 
public void TestNamePropertyCorrectlySetOnInstantiation() 
{ 
    MyClass myInstance = new MyClass("Test name"); 
    Assert.AreEqual("Test Name", myInstance.Name); 
} 

Dieses im Prinzip akzeptabel aussieht, aber der Punkt des Tests ist, dass, wenn die die Klasse zu überprüfen, ob mit einem bestimmten Namen instanziert, die Name-Eigenschaft ist richtig eingestellt, aber es scheitert, wenn bei der Instantiierung etwas schief geht, bevor es überhaupt zur Behauptung kommt.

ich es so Refactoring:

[Test] 
public void TestNamePropertyCorrectlySetOnInstantiation() 
{ 
    MyClass myInstance; 
    string namePropertyValue; 

    Assert.DoesNotThrow(() => myInstance = new MyClass("Test name")); 
    Assert.DoesNotThrow(() => namePropertyValue = myInstance.Name); 
    Assert.AreEqual("Test Name", namePropertyValue); 
} 

aber natürlich jetzt teste ich eigentlich drei Dinge hier; In diesem Test bin ich nicht daran interessiert, zu testen, ob die Instanz von MyClass erfolgreich instanziiert wurde oder ob die Name-Eigenschaft erfolgreich gelesen wurde. Diese Tests werden in einem anderen Fall getestet. Aber wie kann ich die letzte Behauptung testen, ohne vorher die beiden anderen zu behaupten, da es nicht möglich ist, den Test zu machen, wenn die ersten beiden fehlschlagen?

Antwort

12

Haben Sie einfach andere Tests, die überprüfen, dass eine Ausnahme ausgelöst wird, wenn Sie es auf eine ungültige Weise initialisieren. Die erste Form ist an diesem Punkt in Ordnung, IMO.

Persönlich würde ich vermeiden, auf dem Dogma von "einem Assert pro Test" zu hängen. Versuchen Sie, einen logischen Pfad durch den Code zu testen, um eine Granularität zu erzielen, die praktisch sinnvoll ist.

+0

Wahr ... es geht nicht so sehr darum, sich an die "eine pro-Test-Aussage" zu halten, als einen roten Fleck gegen den Test zu sehen, wenn der Code, den er testet, gut funktioniert. – Flynn1179

+0

@ Flynn1179: Warum hast du einen roten Fleck bekommen? Ich verstehe nicht, was du meinst. –

+0

Sorry, ich habe vergessen zu erwähnen; Ich benutze ReSharper, um die nUnit-Tests auszuführen, es erscheint als roter Fleck in der Testliste, wenn ein Test fehlschlägt. Ich habe einige Tests, die wegen eines Fehlers fehlschlagen, bevor ich die eigentliche Behauptung durchführe. – Flynn1179

0

In Ihrem speziellen Beispiel müssen Sie nicht behaupten, dass etwas nicht wirft, wenn es Teil Ihrer Testausführung ist. Dieser Aspekt wurde bereits in Ihrem ersten Test getestet, der deutlich lesbarer ist. Wenn der Konstruktor oder der Eigenschaften-Getter eine Ausnahme auslöst, schlägt NUnit den Test mit einer entsprechenden Fehlermeldung fehl. TBH Ich bin nicht sicher, was ist die Idee hinter Assert.DoesNotThrow(), denn wenn Sie es weglassen, erhalten Sie fast das gleiche Ergebnis - aber definitiv sollten Sie es nicht als Teil der normalen Testausführung verwenden. Der einzige Grund, Ausnahmen als Teil der Sprache zu verwenden, besteht darin, dass Sie nicht nach jeder einzelnen Codezeile auf Fehler prüfen müssen.

+0

Ja, ich dachte, das wäre vielleicht nicht das beste Beispiel. Im Allgemeinen ist es natürlich sehr üblich, dass einige Tests ein "Setup" erfordern, das spezifisch für diesen Test ist, aber nicht direkt mit der Funktionalität, die Sie testen . Ich schaute auf "Assert.Inconclusive" und wickelte vielleicht das "Setup" in einen try/catch, der nicht schlüssig erklärt, wenn es fehlschlägt, aber das wird meinen Code noch weniger lesbar machen. – Flynn1179

0

Grzenio ist in diesem richtig. Der erste, einfachste Beispieltest schlägt fehl, wenn eine Ausnahme ausgelöst wird - es ist nicht nötig, explizit dafür zu testen.

Sie sollten jedoch testen, dass eine Ausnahme ausgelöst wird, wenn ungültige Daten an es übergeben werden.

[Test] 
public void TestInvalidNameThrowsException { 
    MyClass myInstance; 
    string namePropertyValue; 
    Assert.Throws(() => myInstance = new MyClass(null)); 
    Assert.Throws(() => myInstance = new MyClass("INVALID_NAME_125356232356")); 
} 

(zum Beispiel weiß ich nicht, C# ein Bit. Aber man sollte die Idee.)

1

Ich weiß nicht wirklich verstehen, was Sie von bedeuten nicht über Prüfung IMO, over-testing ist so etwas wie der Versuch, private Methoden zu testen.

Ich nehme meine Tests, um die Dokumentation des Codes zu sein. Also, wenn ich mehr als eine Behauptung in einer Aussage habe, dann besteht eine hohe Wahrscheinlichkeit, dass ich die zu testende Methode in mehrere kleinere Methoden umgestalten kann oder manchmal meine Testmethode in mehrere verschiedene Testmethoden aufspalte. Nach der Regel one-assert-pro-test erlaubt es Ihnen, sinnvolle Testmethoden-Namen zu haben, die wiederum die Dokumentation Ihres Codes bilden. Die Namenskonvention, der ich für Testmethoden folge, ist methodenname_scenario_expectation (aus RoyOsheroves Art of Unit Testing). Also, denkt auch an die Dokumentation von Code.Do, Sie denken, dass ein Assert-Willen (abgesehen von der Bestätigung der Erwartung) Ihnen/einigen anderen Entwicklern hilft, den Code besser zu verstehen, dann gehen Sie weiter und schreiben Sie diese Behauptung. Aber, um es noch einmal zu wiederholen, stellen Sie sicher, dass Sie die richtigen Namen für die Testmethoden haben.

+0

Mit "Übertesting" rede ich davon, wenn ein Testfall die Funktionalität des Tests anders als beabsichtigt testet, als eine notwendige Konsequenz der Einrichtung des beabsichtigten Tests. – Flynn1179

Verwandte Themen