Die Sql Data Tools (SSDT) die ich bereits im Blog zum Refactoring gezeigt habe (Refactoring von Datenbanken) bieten noch mehr Möglichkeiten um moderne Software Entwicklung auf T-SQL Code umzulegen. Um den Datenbankcode zu testen, finden wir im Visual Studio nun Unit Tests für Datenbankcode. Damit ist es möglich die Datenbankentwicklung so wie den restlichen Code, testgetrieben durchzuführen.
Zunächst muss die Datenbank in ein Visual Studio Projekt importiert werden. Dieser Schritt ist im oben genannten Blog Eintrag beschrieben. Sobald eine Datenbank als Projekt vorliegt, kann im Visual Studio über den SQL Server Object Explorer im Ordner “Projects” darauf zugegriffen werden.
Im Screenshot sind die Stored Procedures der Nordwind-Datenbank zu erkennen. Das Context-Menü einer SP bietet den Menü Punkt “Create Unit Tests….”
Der folgende Dialog, legt ein neues Testprojekt zusätzlich zum bereits angelegten Datenbankprojekt an. Achtung: die voreingestellte Sprache des Testprojektes ist VB.NET. Sollte diese Sprache einem Leser des Blogs nicht gefallen, man kann sie auch auf C# ändern. (Wer mich kennt, weiß welche Sprache ich wähle)
Als nächstes muss noch die Datenbank Verbindung für die Testläufe gesetzt werden. Entweder werden die Test mit einer bestehenden SQL Datenbank durchgeführt, oder das Projekt wird deployed und dieses als Testdatenbank herangezogen. Wichtig ist, dass als Server (localdb)\projects verwendet wird. die Angabe “.\projects” kann vom Visual Studio nicht aufgelöst werden.
Im Testprojekt wird somit eine neue Testklasse erstellt, die von der Testumgebung des Visual Studios wie ein herkömmlicher UnitTest behandelt wird. Die Besonderheit ist der Editor für T-SQL Code in dem der Test formuliert wird.
Der Test Editor besteht aus einem Editorfenster im oberen Teil und einem Bedingungenfenster im unteren Teil:
Mit den Bedingungen kann der Output des Testcodes validiert werden und diese entscheiden über Erfolg und Misserfolg des Tests. Es gibt 8 Möglichkeiten das SQL Ergebnis zu validieren. Ich entscheide mit für einen simplen Testfall, wo die Anzahl der zurückgegebenen Zeilen 3 betragen soll. Dies wird als “Test Condition” hinterlegt:
Über das Eigenschaften Fenster kann definiert werden, wieviele Zeilen in welchem Recordset erwartet werden.
Der Testcode sieht so aus, daraus ergibt sich, dass die Zeilen im Recordset 1 sein sollten.
-- database unit test for dbo.CustOrdersDetail
DECLARE @RC AS INT, @OrderID AS INT;
SELECT @RC = 0,
@OrderID = 10881;
EXECUTE @RC = [dbo].[CustOrdersDetail] @OrderID;
Wenn wir nun den Test laufen lassen kommt es zum erwarteten negativen Ergebnis:
Das liegt daran, dass in der Datenbank, nachdem sie ausgeliefert wurde keine Daten enthalten sind.
Dafür gibt es die Möglichkeit SQL Skripts zu hinterlegen die entweder vor jedem Test durchgeführt werden, oder einmal an Beginn eines Testlaufes für mehrere Tests ausgeführt werden. Die Attribute sind wohl von Unit Tests bekannt [TestInitialze] oder [ClassInitialize]
Im Fall eines SQL Unit Tests sind die SQL Skripts über die DropDown Boxen im oberen Rand des Editorfensters zu setzen:
Das Sql Skript bereitet die noch leere Datenbank soweit vor, dass der Test erfolgreich durchlaufen kann. In dem Fall wird eine Bestellung mit 3 Bestellzeilen eingetragen. Der mühsame Teil war, alle notwendigen Tabellen mit Demodaten zu befüllen. Das kann in einer kleinen Datenbank schon mal bedeuten 10 oder mehr Tabellen mit Daten zu versehen. Der wichtigste Teil des Insert Codes:
INSERT "Order Details" VALUES(10881,23,9,30,0.2)
INSERT "Order Details" VALUES(10881,61,28.5,30,0.2)
INSERT "Order Details" VALUES(10881,70,15,50,0.2)
Die restlichen Code zeilen, schicke ich gerne per Email. Da die Order Details Tabelle fast nur aus PK Felder besteht mussten auch noch Orders, Products, Categories, Suppliers, Customers und Employees angelegt werden zum Glück muss dieses Skript nicht all zu oft erstellt werden.
Der Lohn der Arbeit ist nun ein erfolgreich laufender Unit Test für die Stored Procedure:
und nun kann nach Herzenslust der Code der SP verbessert und verfeinert werden und wir können jederzeit unseren Code automatisiert testen.