Frage

Zum Beispiel schreibe ich Tests gegen einen CSVReader. Es ist eine einfache Klasse, die Textzeilen aufzählt und spaltet. Sein nur Daseinsberechtigung ist Komma in Anführungszeichen zu ignorieren. Es ist weniger als eine Seite.

Mit dem „Black Box“ der Prüfung der Klasse habe ich Dinge überprüft wie

  • Was passiert, wenn die Datei nicht existiert?
  • Was passiert, wenn ich haben keine Berechtigung, auf die Datei?
  • Was passiert, wenn die Datei hat Nicht-Windows-Zeilenumbrüche?

Aber in der Tat, alle diese Dinge sind das Geschäft der Stream. Meine Klasse arbeitet, ohne etwas über diese Fälle zu tun. Also im Grunde sind meine Tests Fehler fangen von Stream geworfen, und das Verhalten von Rahmen behandelt zu testen. Es fühlt sich an wie eine Menge Arbeit für nichts.

Ich habe die damit verbundenen Fragen gesehen

Meine Frage ist, bin ich dabei den Punkt der „Glaskasten“ Testen, ob ich, was ich weiß zu vermeiden diese Art von Arbeit?

War es hilfreich?

Lösung

Das hängt wirklich von der Schnittstelle Ihres CSVReader, müssen Sie überlegen, was der Benutzer der Klasse erwartet.

Zum Beispiel, wenn einer der Parameter ein Name-Datei und die Datei nicht existiert, was geschehen soll? Dies sollte nicht abhängig sein davon, ob Sie einen Stream Leser oder nicht verwenden. Die Unit-Tests sollten für das beobachtbaren externe Verhalten Ihrer Klasse testen und in einigen Fällen zu graben, etwas tiefer und zusätzlich bestimmte Implementierungsdetails gewährleisten abgedeckt sind, beispielsweise die Datei geschlossen wird, wenn der Leser beendet ist.

Allerdings wollen Sie nicht die Unit-Tests auf alle Details abhängig sein oder wegen einer Implementierung Detail anzunehmen, dass etwas passieren wird.

(In diesem Fall außergewöhnliche Umstände) die Klasse beinhaltet beobachtbares Verhalten

Alle Beispiele Sie in Ihrer Frage erwähnen und daher sollte Unit-Tests haben im Zusammenhang mit ihnen.

Andere Tipps

Ich glaube nicht, sollten Sie Zeit Testen Dinge verschwenden, die nicht Ihren Code sind. Es ist eine Designwahl und keine Test Wahl, ob die Fehler des zugrunde liegenden Rahmen zu handhaben oder lassen Sie sie an den Aufrufer propagieren auf. FWIW, ich glaube, du hast Recht, sie zu lassen propagieren auf. Sobald Sie die Design-Entscheidung getroffen haben, obwohl, sollten Sie Ihre Unit-Tests Ihren Code abdecken (und decken Sie es gut), ohne die zugrunde liegende Framework zu testen. Mit Dependency Injection und ein Mock-Stream ist wahrscheinlich eine gute Idee, auch.

[EDIT] Beispiel für Dependency Injection (siehe Link oben für weitere Informationen)

Nicht Dependency Injection mit wir haben:

public class CvsReader {
   private string filename;
   public CvsReader(string filename)
   {
      this.filename = filename;
   }

   public string Read()
   {
      StreamReader reader = new StreamReader( this.filename );
      string contents = reader.ReadToEnd();
      .... do some stuff with contents...
      return contents;
   }
}

Mit Dependency Injection (Konstruktor Injektion) wir tun:

public class CvsReader {
   private IStream stream;
   public CvsReader( IStream stream )
   {
      this.stream = stream;
   }

   public string Read()
   {
       StreamReader reader = new StreamReader( this.stream );
       string contents = reader.ReadToEnd();
       ...  do some stuff with contents ...
       return contents;
   }
}

Dies ermöglicht es der CvsReader leichter überprüfbar zu sein. Wir passieren eine Instanz der Umsetzung der Schnittstelle wir im Konstruktor hängen von, in diesem Fall IStream. Aus diesem Grunde können wir eine andere Klasse (vielleicht eine Mock-Klasse) erstellen, die IStream implementiert, ist aber nicht unbedingt tun, Datei-I / O. Wir können diese Klasse verwenden, um unsere Leser zu füttern, was Daten, die wir wollen, ohne dass der zugrunde liegenden Rahmen beteiligt sind. In diesem Fall würde ich ein Memorystream verwenden, da wir gerade von ihm zu lesen. In wir allerdings zu, wollten, könnten wir eine Mock-Klasse verwenden und ihm eine reichere Schnittstelle geben, die unsere Tests können konfigurieren, dass die Antworten, die es gibt. Auf diese Weise können wir den Code testen, die wir schreiben und nicht den zugrunde liegenden Framework-Code überhaupt einbeziehen. Alternativ könnten wir auch einen Textreader passieren, aber die normale Dependency Injection Muster verwendet Schnittstellen und ich wollte das Muster mit Schnittstellen zeigen. Wohl in einem Textreader vorbei wäre besser, da oberhalb der Code immer noch abhängig ist von der Stream Umsetzung.

Ja, aber das ausschließlich für die Zwecke der Unit-Tests wäre:

Sie könnten abstrakt Ihre CSV-Leser Implementierung von einem bestimmten Stream durch eine abstrakte Stromleser-Schnittstelle definiert, und mit einem Mock-Stream-Leser eine eigene Implementierung zu testen, die diese Schnittstelle implementiert. Ihr Mock Leser offensichtlich immun sein würde, um Fehler wie nicht vorhandene Dateien, die Erlaubnis Probleme, OS Unterschiede usw. Sie würden daher ausschließlich in Ihrem eigenen Code testen und kann zu 100% Codeabdeckung erreichen.

ich mit tvanfosson eher zustimmen: Wenn Sie von einem Stream erben und erweitern sie in irgendeiner Weise, sollten Sie Ihre Unit-Tests nur ausüben, um die Funktionalität hinzugefügt oder geändert haben. Sonst wirst du eine Menge Zeit und Energie kognitiven Schreiben, Lesen und Aufrechterhaltung Tests Abfälle, die keinen Mehrwert haben.

Obwohl MarkJ richtig ist, dass die Tests sollten das „beobachtbare äußere Verhalten“ einer Klasse abdecken, ich denke, es angemessen ist, zu prüfen, mit das Verhalten kommt. Wenn es Verhalten über Vererbung ist von einer anderen (vermutlich Einheit getestet) Klasse, dann sehe ich keinen Nutzen in Ihrer eigene hinzufügen Einheit Tests. OTOH, wenn es Verhalten über Zusammensetzung dann es Macht einige Tests rechtfertigen die Durchführungen, um sicherzustellen, ordnungsgemäß funktionieren.

Meine Präferenz zu Unit-Test Sie ändern, die spezifische Funktionalität und dann schreiben Integration Tests, die für Fehlerbedingungen überprüfen wäre, aber im Rahmen des Geschäfts brauchen sind Sie letztlich zu unterstützen.

Nur ein FYI, wenn diese .NET ist, sollten Sie nicht das Rad neu zu erfinden.

Für C #

Fügen Sie einen Verweis auf Microsoft.VisualBasic Verwenden Sie die fantastische Klasse Microsoft.VisualBasic.FileIO.TextFieldParser (), um Ihre CSV-Parsing-Anforderungen zu verarbeiten.

Microsoft bereits getestet, so dass Sie nicht haben.

Genießen.

Sie sollten immer Fehler werden die Verwaltung, dass Ihr Rahmen wirft; auf diese Weise Ihre Anwendung ist robust und nicht abstürzen nicht auf katastrophale Fehler ...

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