TDD mit SQL- und Datenmanipulationsfunktionen


14

Während ich ein professioneller Programmierer bin, wurde ich noch nie in Software-Engineering ausgebildet. Da ich häufig hier bin und SO, habe ich einen Trend festgestellt, wann immer möglich Unit-Tests zu schreiben, und da meine Software komplexer und ausgefeilter wird, sehe ich automatisierte Tests als eine gute Idee, um das Debuggen zu unterstützen.

Der Großteil meiner Arbeit besteht jedoch darin, komplexes SQL zu schreiben und die Ausgabe dann auf irgendeine Weise zu verarbeiten. Wie würden Sie beispielsweise einen Test schreiben, um sicherzustellen, dass Ihre SQL die richtigen Daten zurückgibt? Sagen Sie dann, wenn die Daten nicht unter Ihrer Kontrolle standen (z. B. die eines Drittanbieter-Systems), wie können Sie Ihre Verarbeitungsroutinen effizient testen, ohne Unmengen von Dummy-Daten schreiben zu müssen?

Die beste Lösung, die ich mir vorstellen kann, besteht darin, Ansichten der Daten zu erstellen, die zusammen die meisten Fälle abdecken. Ich kann dann diese Ansichten mit meinem SQL verknüpfen, um festzustellen, ob die richtigen Datensätze zurückgegeben werden, und die Ansichten manuell verarbeiten, um festzustellen, ob meine Funktionen usw. das tun, was sie sollen. Trotzdem wirkt es übertrieben und flockig; insbesondere Daten zu finden, gegen die getestet werden soll ...


Antworten:


6

Eine wichtige Regel zum Testen aller datenbankbezogenen Elemente besteht darin, sie vollständig von der übrigen Anwendung zu isolieren.

Die Architektur der Ports und Adapter ist ein wirklich gutes Beispiel. Die Datenbank wird als externes Plugin über einen Adapter für Ihre Anwendung betrachtet. Gleiches gilt für alle Subsysteme von Drittanbietern. Um zu testen, wie sich Ihre App verhält und die Antworten von Subsystemen von Drittanbietern zu interpretieren, kann ich nur testen, wie die Antworten dieses einzelnen Subsystems gestubpt werden. Ich meine nicht unbedingt, dass Sie alle Datenobjekte manuell schreiben müssten. Sie können ganz einfach datengesteuerte Tests verwenden.

Wenn Sie testen möchten, wie Ihre Anwendung mit Ihrer Datenbank interagiert, können Sie die Datenbankadapter so anpassen, dass sie beispielsweise eine In-Memory-Datenbank verwenden.

Testen Sie jetzt Ihre Datenbankabfragen. Zunächst sollten die komplexen Abfragen in einfachere, einfachere und vorhersehbarere Abfragen zerlegt werden. Das gleiche würden Sie für eine fette Kategorie oder für eine fette Funktion tun. Es gibt Tools, mit denen Sie Ihre Datenbank wie Dbunit testen können. Ein einfacher Ansatz, den ich manchmal verfolge, ist die Verwendung des Konzepts der Charakterisierungstests. Also würde ich die Datenbank in einen bekannten Zustand versetzen, alle Abfragen ausführen, die ich schreiben muss, und die Ausgabe an einem Ort (Datei, Speicher) speichern und diese Ausgabe als die richtige betrachten. Die nächsten Läufe würden ihre Ausgabe mit dieser vergleichen, so dass mir definitiv die Regressionstests angeboten würden, die ich brauche. Es ist zwar nicht garantiert, dass die erste Ausgabe korrekt ist, aber das Regressionsproblem kann auf diese Weise gelöst werden. Wenn Sie Ihre Abfragen gut zerlegt haben, können Sie sie einzeln in Bezug auf die Datenbank testen, die sich in einem bekannten Zustand befindet.


3

Dies ist eine interessante Frage, da die Datenbank normalerweise der Teil ist, der beim Testen von Anwendungseinheiten gefälscht wird. Hoffentlich wird die Logik des Datenbankmoduls selbst vom Anbieter gut getestet, aber natürlich sind die Abfragen, das Schema und die gespeicherten Prozeduren Code, der getestet und vor Regression geschützt werden muss. Dies wird oft den Integrationstests überlassen, bei denen es sich nicht um TDD handelt.

Ansichten wären wahrscheinlich eine schwierige Methode, da sie dem Test nicht wirklich das erste automatische Testen mit rotem und grünem Licht für einen Aspekt pro Test verleihen, der in TDD bevorzugt wird. Auch bei Views kann man den Test nicht erst vor dem Code schreiben. Ein besserer Ansatz wäre, gespeicherte Prozeduren zu schreiben, bei denen Sie der Prozedur "assert" -Logik hinzufügen können (z. B. mithilfe von "if" -Anweisungen), um die Ausgabe auf Fehler zu testen. Sie müssen in jedem Einheitentest nur eine Sache testen, um die Einheit zu isolieren, und die SP-Methode wäre dafür besser geeignet. Außerdem können Sie mit SPs die gesamte Suite als Skripte ausführen, während Sie den ursprünglichen Code entwickeln, und später beim Testen auf Regressionen beim Refactoring.

Beachten Sie auch, dass die Tests wiederholbar sein müssen und Sie einige Skripte benötigen, um den Datenbankstatus zu initialisieren und herunterzufahren, um sicherzustellen, dass der Status für jeden Komponententest identisch ist.

Für Ihre Frage zu Daten, die nicht unter Ihrer Kontrolle stehen, ist das ein schwieriger Bereich. Ich denke, Sie sind besser dran, es mit gefälschten Daten zu verspotten und die Ausnahmebedingungen und Randbedingungen so weit wie möglich für Komponententests zu testen. Andernfalls wird es mehr in die Kategorie der Integrationstests fallen (was auch eine gute Sache ist, zu tun). Für Integrationstests können Sie Ihre Tests mit den Daten von Drittanbietern ausführen und eine erste Ausgabe generieren lassen. Für nachfolgende Tests (z. B. nach dem Refactoring) müssen Sie sicherstellen, dass diese Ausgaben die erste bekannte Ausgabe wiederholen.


Warum können Sie keinen Test für eine Ansicht schreiben, die noch nicht codiert wurde?
JeffO

Nicht, wenn Sie die vom OP vorgeschlagene Ansicht als Testmechanismus verwenden.
Schlüsselfertige

1

Irgendwann werden Sie Testdaten benötigen. Wenn Sie ein System eines Drittanbieters verwenden, wurde das Schema bereits erstellt, Sie müssen jedoch zukünftige Änderungen berücksichtigen. Hoffentlich können Sie diese Änderungen aus der Upgrade-Dokumentation abrufen, müssen jedoch möglicherweise die Datenbankversionen selbst vergleichen.

Die erwarteten Ergebnismengen können in Datenbanktabellen oder externen Dateien / Tabellen gespeichert werden. Ich habe sogar CHECKSUM oder Vergleiche gesehen. Beim Testen einer Ansicht / eines Sprocs tritt ein Fehler auf, da diese nicht vorhanden sind. Dann erstellen Sie das Objekt mit genügend Code, um es zumindest auszuführen (SELECT -1 as [wrong_data];), und Sie erhalten einen Fehler, weil es nicht mit der Ergebnismenge übereinstimmt. Sobald sie zusammenpassen, haben Sie Ihr grünes Licht.

Ich habe angefangen, mit Projektbesitzern zu arbeiten und sie zu bitten, Berichte in einer Tabelle zu verspotten und zu versuchen, Teildaten für mich zu finden (Sie könnten die Ergebnisdaten in eine Testtabelle schreiben.). Anfangs gab es einige Rückschläge, aber sie haben erkannt, dass ich einen Bericht erstellen werde und sie müssen ihn trotzdem überprüfen. Dies hat auf lange Sicht Zeit gespart. Wenn sie eine Änderungsanforderung stellen möchten, können sie die Tabelle wiederholen. Jetzt können sie die Frage beantworten: "Wie schwer wäre es, ... hinzuzufügen?"


1

Wenn Ihre Datenbankplattform SQL Server ist, gibt es ein sehr schönes kostenloses Tool: tSQLt .

tSQLt ist ein Framework zum Testen von Datenbankeinheiten für Microsoft SQL Server. tSQLt ist mit SQL Server 2005 (Service Pack 2 erforderlich) und höher in allen Editionen kompatibel.

Ich habe erfolgreich verwendet, um Tests auf Datenbankebene zu implementieren.

Einige der wichtigsten Elemente, die es so nützlich machen, sind:

  • Die Fähigkeit, mit gefälschten Tabellen und Ansichten zu arbeiten, reduziert die damit verbundene normale Einrichtung
  • Tests werden automatisch in Transaktionen ausgeführt (so einfach, dass sie erneut ausgeführt werden können)
  • Ihre Asserts können Vergleiche für Tabellen (sowohl echte als auch gefälschte) durchführen, sodass Sie leicht feststellen können, ob Sie Daten geändert haben
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.