Unit Tests sind ein zentraler Bestandteil der modernen Datenbankentwicklung. Mit tSQLt, einem Open-Source-Framework für SQL Server, kannst du deine Stored Procedures und Funktionen in isolierten Testszenarien prüfen. Dabei wird jeder Testfall in einer einzigen Transaktion ausgeführt, die am Ende automatisch zurückgerollt wird. Das stellt sicher, dass deine Tests keine dauerhaften Änderungen in der Datenbank hinterlassen.
Wie funktionieren Transaktionen in tSQLt?
tSQLt startet für jeden Test eine sogenannte Ambient Transaction. Das heißt:
- Alle Änderungen, die im Rahmen des Tests vorgenommen werden, erfolgen in dieser Transaktion.
- Am Ende des Tests wird die Transaktion zurückgerollt, sodass alle Teständerungen (z. B. INSERTs, UPDATEs, DELETEs) verworfen werden.
- Dies gilt auch für Operationen, die über vollqualifizierte Namen (z. B. [BITest].xy.myOrder) aufgerufen werden – sofern alle Operationen über dieselbe Verbindung laufen.
Wenn du jedoch möchtest, dass bestimmte Änderungen dauerhaft in der Datenbank gespeichert werden – beispielsweise Logeinträge, die den Testverlauf dokumentieren – musst du diese Änderungen in einen separaten, unabhängigen Verbindungskontext auslagern. tSQLt bietet hierzu die Prozedur tSQLt.NewConnection an, mit der du Befehle über eine neue Verbindung ausführst. Befehle, die so ausgeführt werden, sind nicht Teil der übergeordneten Testtransaktion und werden sofort committet.
Persistentes Logging – Das Konzept
Stell dir vor, du möchtest in einem Unit Test zwei Logeinträge erzeugen:
- Ein direkter INSERT in eine Log-Tabelle, der Teil der Testtransaktion ist und somit nach Testende zurückgerollt wird.
- Ein INSERT über tSQLt.NewConnection, der über eine separate Verbindung ausgeführt wird und sofort committet wird – dieser Eintrag bleibt dauerhaft bestehen.
Während des Testlaufs sind beide Einträge vorhanden. Nach Abschluss des Tests und dem automatischen Rollback bleiben dann nur der Eintrag erhalten, der über tSQLt.NewConnection geschrieben wurde.
Praktisches Beispiel: Persistentes Logging mit zwei Logeinträgen
Im folgenden Beispiel wird gezeigt, wie du in der Datenbank BITest eine persistent Log-Tabelle (dbo.PersistentLog) erstellst, und wie du in einem unabhängigen Unit Test zwei Logeinträge erzeugst. Anschließend wird überprüft, dass – nach Rollback – nur der über tSQLt.NewConnection geschriebene Eintrag in der Log-Tabelle erhalten bleibt.
1. Persistent-Tabelle erstellen
Zunächst wird die Tabelle dbo.PersistentLog angelegt. Diese Tabelle soll alle Logeinträge aufnehmen, die dauerhaft gespeichert werden.
2. Testklasse “LogTests” erstellen
tSQLt implementiert Testklassen als Schemas. Hier prüfen wir, ob das Schema LogTests bereits existiert; falls nicht, wird es mittels tSQLt.NewTestClass erstellt.
3. Unit-Test: Persistentes Logging mit zwei Logeinträgen
Dieser Test führt zwei INSERTs in die Tabelle dbo.PersistentLog aus:
- Schritt 1: Über tSQLt.NewConnection wird ein Logeintrag eingefügt, der sofort committet wird und somit dauerhaft erhalten bleibt.
- Schritt 2: Ein direkter INSERT wird ausgeführt, der Teil der Testtransaktion ist und somit am Ende zurückgerollt wird.
- Anschließend wird überprüft, dass während des Tests beide Einträge vorhanden sind. Nach Abschluss des Tests (Rollback) sollte dann nur der dauerhaft committete Eintrag in der Log-Tabelle verbleiben.
Zusammenfassung und Fazit
In diesem Artikel haben wir gezeigt, wie tSQLt alle Unit Tests in einer übergeordneten Transaktion ausführt, sodass Änderungen, die direkt im Test gemacht werden, am Ende zurückgerollt werden. Mit der Prozedur tSQLt.NewConnection kannst du jedoch Befehle in einem separaten Verbindungskontext ausführen, sodass diese Änderungen sofort committet werden und nicht vom Rollback betroffen sind.
Unser Beispiel demonstriert dies anhand eines Loggingszenarios:
- Ein direkter INSERT (Teil der Testtransaktion) wird nach Testende zurückgerollt.
- Ein INSERT über tSQLt.NewConnection wird dauerhaft in der persistenten Tabelle dbo.PersistentLog gespeichert.
- Während des Tests sind beide Logeinträge vorhanden, nach Rollback bleibt nur der dauerhaft committete Eintrag bestehen.
Diese Technik ist besonders nützlich, wenn du Testresultate, Fehlerberichte oder andere wichtige Informationen über den Testlauf hinweg dokumentieren möchtest – ohne die Isolation deiner Unit Tests zu gefährden.