Laden...

Problem mit Reihenfolge von Unit-Tests bei inversen Operationen (Laden und Speichern von Echtdaten)

Erstellt von Wax vor 11 Jahren Letzter Beitrag vor 11 Jahren 1.422 Views
Wax Themenstarter:in
731 Beiträge seit 2006
vor 11 Jahren
Problem mit Reihenfolge von Unit-Tests bei inversen Operationen (Laden und Speichern von Echtdaten)

Hallo zusammen,

ich schreibe seit geraumer Zeit UnitTest´s da ich (glaube ich zumindest) nach dem TDD-Schema entwickle.

Dabei drängt sich mir folgende Frage immer mehr auf:

Stellen wir uns vor ich habe 2 Methoden. Die eine schreibt Daten in eine Datenbank und die andere kann diese Daten wieder aus der Datenbank abrufen.
Wenn ich für diese Methoden nun Tests schreiben möchte, wie hält man es dann mit der Reihenfolge der Aktionen/Tests?

Sollte man nun im Test zum Laden zuerst den Test zum schreiben aufrufen oder sollten die Tests generell unabhängig, also ohne benötigte Reihenfolge, durchgeführt werden können?

MfG
wax

3.511 Beiträge seit 2005
vor 11 Jahren

Tests sollten im Normalfall immer unabhängig voneinander laufen.

In deinem Fall sollte der Speichern Test natürlich in eine DB schreiben um zu schauen, ob die Daten korrekt ankommen. Das Laden hingegen sollte natürlich vom Schreiben unabhängig sein. Sprich die Daten müssen schon da sein. Sowas lößt man dann normalerweise über Mocks, die die entsprechenden Daten bereitstellen. Ich kenne deine Architektur nicht, aber wenn du z.B. mit Repositories arbeitest, ist es relativ simpel sowas zu mocken.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

Wax Themenstarter:in
731 Beiträge seit 2006
vor 11 Jahren

Hi Khalid,

sind Mocks nicht nur dazu da um Schnittstellen (Übergabepunkte) zu testen?
In meinem Fall kann es nicht sein, dass das Laden eines Objekts jemals anders Implementiert wird als über die aktuell existierende Methode (also per DB-Zugriff).
Wenn ich nun ein Mock benutzen würde, dann wüsste ich ja nicht wirklich ob der ganze Datenbankzugriffs-Kladderadatsch im Hintergrund wirklich funktioniert, da ich mir doch die Daten "vorgaukeln" würde.
Oder sehe ich das falsch?

MfG
wax

3.511 Beiträge seit 2005
vor 11 Jahren

sind Mocks nicht nur dazu da um Schnittstellen (Übergabepunkte) zu testen?

Das Laden der Daten läuft bei dir nicht über Interfaces? Kann ich mir fast nicht vorstellen.

Wie gesagt, ich kenne deine Architektur nicht. Das hängt IMHO von der Architektur ab. Meine "Lade dies und das" Tasks, holen ihre Daten z.B. über Mocks ab. Trotzdem kann ich die Logik dahinter testen. Die Daten sind zwar statisch, aber jeder Fall ist definiert.

Beispiel:


public interface ILadeTask
{
  IList<Daten> HoleDieDaten(DateTime von, DateTime bis);
}

public class LadeTask: ILadeTask
{
  private readonly IRepository<Daten> m_Repository;

  public LadeTask(IRepository<Daten> repository)
  {
    m_Repository = repository;
  }

  public IList<Daten> HoleDieDaten(DateTime von, DateTime bis)
  {
    return m_Repository.Where(x => x.Von >= von && x.Bis <= bis).ToList();
  }
}

Das Repository wird gemockt. Die Logik die korrekten Daten zu holen, liegt in der Implementation des Interfaces ILadeTask. Per IoC werden in den Tests jetzt die "statischen" Repositories reingeklinkt.

Keine Ahnung, ob dies jetzt der 100% richtige Weg ist, aber ich fahre damit sehr gut. Bei Massendaten kann ich somit z.B. das Mock Repository gegen ein z.B. Sqlite DB Repository jagen und mein ILadeTask tut immer noch das was es soll.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

F
10.010 Beiträge seit 2004
vor 11 Jahren

Und wann testet ihr mit echten Daten?

Haben wir auch mal nur mit repositories gemacht, man hat das "gerummst" und "gepoltert" als wir dann mit einer grossen echten DB gearbeitet haben.

Manchmal muss sowas auch auf Echtdaten laufen.

3.511 Beiträge seit 2005
vor 11 Jahren

Und wann testet ihr mit echten Daten?

Über anschließende Integrationstest, in dem die gesamten Workflows nochmal zusammengesetzt getestet werden. IMHO machen große Datenmengen bei Unit-Tests keinen Sinn. Ich kann mich da auch gerne irren 😃

Manchmal muss sowas auch auf Echtdaten laufen.

Da gebe ich dir vollkommen recht. Manuell kann ich jederzeit die Tests gegen Echt-DBs umschwenken (Sqlite, MSSQL, usw...). Passiert aber sehr selten, da dies halt die Integrationstests machen. Und die sagen mir auch früh genug bescheid, wenn was knallt, bzw. wenn bestimmte Timeouts überschritten werden.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

49.485 Beiträge seit 2005
vor 11 Jahren

Hallo Wax,

grundsätzlich kannst du auch solche eng verbundenen Methoden unabhängig voneinander testen. Man muss sich nur überlegen, wann die Speicher-Methode korrekt ist. Doch nicht, wenn die Lade-Methode die Daten genau so liefert, wie sie in die Speicher-Methode gepackt wurden, sondern wenn die Daten so in der Datenbank stehen, wie sie stehen sollen.

Es ist sogar denkbar, dass wenn eine Lade-Methode die Daten exakt so liefert, wie sie gespeichert wurden, dies ein Indiz dafür sein kann, dass die Daten nicht korrekt gespeichert wurden.0 Stell dir vor, im zu speichernden Objekt ist eine Längenangabe im Metern enthalten, die aber in der Datenbank in Fuß abgelegt werden soll. Dann ist beim Speichern eine Umrechnung erforderlich, die typischerweise kleinen zu Rundungsfehlern führt. Sollte sowohl die Speicher-Methode als auch die Lade-Methode die Umrechnung vergessen, wird zwar der exakte Wert zurückgeliefert, aber in der Datenbank steht trotzdem der falsche Wert.

Das Blöde daran ist nur, dass man bei Unit-Tests die Korrektheit automatisiert bestimmen können will. Das heißt man kommt nicht drum herum, die gerade gespeicherten Daten aus der Datenbank zu lesen und zu vergleichen. Und natürlich kann man in der Praxis abwägen, ob man das nicht einfach mit der sowieso vorhanden Lade-Methode tut.

Das bedeutet jedoch, dass die Lade-Methode korrekt sein muss, also zuerst getestet werden muss. Und das geht glücklicherweise auch ohne die Speicher-Methode, also ohne dass sich die Katze in den Schwanz beißt. Denn um die Lade-Methode zu testen, reicht es - z.B. mit einem entsprechenden vorhandenen Import-Tool -, einen definierten (Test-)Datenbestand in die Datenbank zu packen und dann per Unit-Test zu prüfen, ob die Lade-Methode die Daten so liefert, wie definiert.

Lange Rede, kurzer Sinn: zuerst die Lade-Methode testen und dann die Speicher-Methode.

herbivore