5 Stimmen

.NET Unit Testing - Best Practices zum Verstecken von Testnähten im Release-Code

Ich bin auf der Suche nach einigen Ratschlägen für Unit-Testing in einer Weise, die nicht verlassen "Test-Haken" in Ort in der Produktion Code.

Nehmen wir an, ich habe eine statische Klasse (VB.NET-Modul) namens MethodLogger, die eine Methode "void WriteEntry(string Message)" hat, die die aufrufende Methode und eine Nachricht in eine Protokolldatei auf der Festplatte schreiben soll. Das eigentliche Ziel von WriteEntry() kann auf eine Fake-Implementierung von IMethodLogger umgeleitet werden, um Unit-Tests durchzuführen, und für todos in anderen Fällen sollte es die eigentliche Implementierung von IMethodLogger aufrufen.

Hier ist ein grober Schnitt von dem, was ich bis jetzt ausgeheckt habe, und ich mag den Ansatz - aber in einigen schnellen Tests wirft er einige Fragen und Zweifel auf:

[InternalAttributesVisibleTo("MethodLogger.Tests")]
internal static class MethodLogger
{
    public void WriteEntry(string message)
    {
        LogWriter.WriteEntry(message);
    }

    private IMethodLogger LogWriter
    {
        get;
        set;
    }

#if DEBUG
    internal void SetLogWriter(IMethodLogger logger)
    {
        LogWriter = logger;
    }
#endif
}

Hier sind meine konkreten Fragen:

  • Diese eng Paare die Unit-Tests gegen die DEBUG-Build ausgeführt; wenn ich Unit-Tests ausführen, obwohl es scheint, dass es nicht speziell die Baugruppe unter Test in DEBUG neu erstellen--ist es möglich, dies zu tun?

    • Würde ich die Unit-Tests jemals gegen einen nicht-debuggen Build laufen lassen wollen? Von der Spitze von meinem Kopf sehe ich weniger Wert - aber würde es sein?
  • Wäre es für mich möglich, ein benutzerdefiniertes Pre-Compiler-Flag wie "TEST" anstelle von "DEBUG" zu verwenden? Wie würde ich Visual Studio anweisen, das Ziel immer neu zu erstellen? mit diese Flagge zum Testen, um sicherzustellen, dass meine Haken/Nähte verfügbar sind?

3voto

Lou Franco Punkte 85315

Wir stellen sicher, dass wir Tests gegen Release/Obfuscated-Builds durchführen, weil wir auf diese Weise oft Probleme aufgedeckt haben, also ja, ich denke, es ist sinnvoll, sie zum Laufen zu bringen.

Die Verschleierung macht Interna völlig unbrauchbar, und das ist gut genug für mich, also lassen wir die Testmethoden drin (und machen sie intern).

Im Großen und Ganzen ist es mir lieber, dass der Code getestet wird, als dass ich mir Gedanken darüber mache, ob sie vorhanden sind - solange sie die Leistung nicht beeinträchtigen.

3voto

Jon Skeet Punkte 1325502

Mir persönlich gefällt der Gedanke nicht, die Tests nicht mit den echten Produktions-Binärdateien durchführen zu können.

Könnten Sie nicht einfach den Setter als "veraltet" markieren und die Warnung vor veralteten Funktionen in Ihrem Testcode deaktivieren? Zusammen mit einer angemessenen Dokumentation sollte das verhindern, dass der Produktionscode ihn versehentlich aufruft, und ihn dennoch für die Tests verfügbar machen.

Um jedoch auf Ihre eigentlichen Fragen einzugehen:

  • Ja, es ist sinnvoll, Unit-Tests gegen Nicht-Debug-Builds laufen zu lassen - das gibt mehr Sicherheit, dass Änderungen zwischen Debug- und Nicht-Debug-Builds nichts kaputt machen.
  • Ja, Sie können Ihr eigenes Präprozessor-Symbol (z. B. TEST) verwenden, wenn Sie wollen; Sie können das entweder in den vorhandenen Konfigurationen anwenden oder eine neue Build-Konfiguration erstellen.

2voto

Finglas Punkte 15260

Mit #IF DEBUG usw... ist schlechtes Benehmen.

Der Produktionscode sollte unabhängig vom Test-/Debug-Code sein.

Ich würde raten, sich mit Dependency Injection zu beschäftigen, um Unit-Tests zu unterstützen.

2voto

Gavin Chin Punkte 558

Nach Michael Feathers Buch "Working Effectively with Legacy Code" scheint es besser zu sein, wenn Sie den Setter etwas Spezifisches zum Testen nennen.

Beispiel: SetTestingLogger(IMethodLogger logger)

Ich würde auch die Präprozessoranweisungen entfernen. Im Buch heißt es außerdem, und ich zitiere

"Der Gedanke, dass Sie den Zugang die Vorstellung, dass Sie den Zugriffsschutz aufheben Schutz aufheben, wenn Sie statische Setter verwenden, aber denken Sie daran, dass der Zweck des Zugriffsschutzes ist es, Fehler zu verhindern Fehler zu verhindern. Wir fügen Tests ein, um auch Fehler zu verhindern."

Schlussfolgerung: Es scheint, dass es am besten wäre, diese Haken einzubauen, weil Sie sie zum Testen und letztlich zur Fehlerbeseitigung einbauen.

Der Abschnitt "Introduce Static Setter" in dem Buch erklärt dies im Detail. Ich würde es als ein Buch empfehlen, das jeder Entwickler haben sollte.

2voto

azheglov Punkte 5375
  1. wie bereits gesagt, Umstellung auf Dependency Injection und Inversion-of-Control (IoC)
  2. die zu testenden Klassen mit Hilfe von Isolations-Frameworks (Moq usw.) gut isolieren
  3. Tests in eine separate Assembly verschieben - keine Notwendigkeit für #if DEBUG... #endif

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X