Ich programmiere in Java und meine Anwendungen nutzen DB sehr häufig. Daher ist es wichtig, dass ich meine DB-Nutzung einfach testen kann.
Worum geht es bei DB-Tests? Für mich sollten sie zwei einfache Anforderungen erfüllen:
- Überprüfen Sie die SQL-Syntax.
- Noch wichtiger ist, überprüfen Sie, ob die Daten je nach Situation korrekt ausgewählt / aktualisiert / eingefügt wurden.
Nun, es scheint, dass ich nur eine DB brauche.
Aber eigentlich bevorzuge ich nicht, da es nur wenige Schwierigkeiten gibt, eine DB für einen Test zu verwenden:
- "Hol dir einfach eine Test-DB, wie schwer könnte es sein?" - An meinem Arbeitsplatz ist es ziemlich unmöglich, eine persönliche Test-DB zu haben. Sie müssen eine "öffentliche" Datenbank verwenden, auf die jeder zugreifen kann.
- "Diese Tests sind sicher nicht schnell ..." - DB-Tests sind in der Regel langsamer als übliche Tests. Es ist wirklich nicht ideal, langsame Tests zu haben.
- "Dieses Programm sollte auf jeden Fall funktionieren!" - Es wird etwas nervig und sogar unmöglich, jeden einzelnen Fall in einer DB zu simulieren. Für jeden Fall sollte eine bestimmte Anzahl von Abfrage- / Aktualisierungsabfragen durchgeführt werden, was ärgerlich ist und Zeit in Anspruch nimmt.
- "Moment mal, woher weißt du, dass diese Tabelle 542 Zeilen enthält?" - Eines der Hauptprinzipien beim Testen ist es, die Funktionalität auf eine Weise testen zu können, die sich von der Ihres getesteten Codes unterscheidet. Wenn Sie eine Datenbank verwenden, gibt es normalerweise eine Möglichkeit, etwas zu tun. Daher ist der Test genau der gleiche wie der Kerncode.
Sie können also herausfinden, dass ich DBs nicht mag, wenn es um Tests geht (natürlich muss ich irgendwann darauf zurückkommen, aber ich würde lieber später zu meinen Tests kommen, nachdem ich die meisten Fehler mit dem gefunden habe Rest der Testmethoden). Aber wonach suche ich?
Ich suche nach einer Möglichkeit, eine Datenbank, eine Scheindatenbank, mithilfe des Dateisystems oder nur des virtuellen Speichers zu simulieren. Ich dachte, dass es vielleicht ein Java-Tool / -Paket gibt, mit dem einfach (mithilfe der Codeschnittstelle) ein DB-Modell pro Test mit simulierten Tabellen und Zeilen, mit SQL-Überprüfung und mit einer Codeschnittstelle zur Überwachung des Status erstellt werden kann (anstatt SQL zu verwenden) ).
Kennen Sie diese Art von Werkzeug?
Edit: Danke für die Antworten! Obwohl ich nach einem Tool gefragt habe, haben Sie mir auch einige Tipps zum Problem gegeben :) Es wird einige Zeit dauern, bis ich Ihre Angebote überprüft habe. Daher kann ich derzeit nicht sagen, ob Ihre Antworten nicht zufriedenstellend waren.
Hier ist eine bessere Übersicht über das, wonach ich suche: Stellen Sie sich eine Klasse mit dem Namen DBMonitor vor, die unter anderem die Anzahl der Zeilen in einer Tabelle ermittelt. Hier ist ein imaginärer Code, wie ich diese Funktion mit JUnit testen möchte:
public class TestDBMonitor extends TestCase {
@Override
public void setUp() throws Exception {
MockConnection connection = new MockConnection();
this.tableName = "table1";
MockTable table = new MockTable(tableName);
String columnName = "column1";
ColumnType columnType = ColumnType.NUMBER;
int columnSize = 50;
MockColumn column = new MockColumn(columnName, columnType, columnSize);
table.addColumn(column);
for (int i = 0; i < 20; i++) {
HashMap<MockColumn, Object> fields = new HashMap<MockColumn, Object>();
fields.put(column, i);
table.addRow(fields);
}
this.connection = connection;
}
@Test
public void testGatherStatistics() throws Exception {
DBMonitor monitor = new DBMonitor(connection);
monitor.gatherStatistics();
assertEquals(((MockConnection) connection).getNumberOfRows(tableName),
monitor.getNumberOfRows(tableName));
}
String tableName;
Connection connection;
}
Ich hoffe, dieser Code ist klar genug, um meine Idee zu verstehen (entschuldigen Sie mich für Syntaxfehler, ich habe manuell ohne meine liebe Eclipse: P getippt).
Übrigens verwende ich ORM teilweise und meine rohen SQL-Abfragen sind recht einfach und sollten sich nicht von einer Plattform zur anderen unterscheiden.
Java wird mit Java DB geliefert .
Trotzdem würde ich davon abraten, einen anderen DB-Typ als den in der Produktion verwendeten zu verwenden, es sei denn, Sie durchlaufen eine ORM-Schicht. Andernfalls ist Ihr SQL möglicherweise nicht so plattformübergreifend, wie Sie denken.
Schauen Sie sich auch DbUnit an
quelle
Ich habe Hypersonic für diesen Zweck verwendet. Grundsätzlich handelt es sich um eine JAR-Datei (eine reine Java-In-Memory-Datenbank), die Sie in einer eigenen JVM oder in Ihrer eigenen JVM ausführen können. Während der Ausführung verfügen Sie über eine Datenbank. Dann stoppen Sie es und Ihre Datenbank verschwindet. Ich habe es - bisher - als reine In-Memory-Datenbank verwendet. Es ist sehr einfach, über Ant zu starten und zu stoppen, wenn Unit-Tests ausgeführt werden.
quelle
Es gibt viele Gesichtspunkte zum Testen von Integrationspunkten wie der Datenbankverbindung über SQL. Mein persönliches Regelwerk, das für mich gut funktioniert hat, lautet wie folgt:
1) Trennen Sie die Datenbankzugriffslogik und -funktionen von der allgemeinen Geschäftslogik und verstecken Sie sie hinter einer Schnittstelle. Grund: Um die große Mehrheit der Logik im System zu testen, ist es am besten, einen Dummy / Stub anstelle der eigentlichen Datenbank zu verwenden, da dies einfacher ist. Grund 2: Es ist dramatisch schneller
2) Behandeln Sie Tests für die Datenbank als Integrationstests, die vom Hauptteil der Komponententests getrennt sind und auf einer Setup-Datenbank ausgeführt werden müssen. Grund: Geschwindigkeit und Qualität der Tests
3) Jeder Entwickler benötigt eine eigene Datenbank. Sie benötigen eine automatisierte Methode, um ihre Struktur basierend auf Änderungen ihrer Teamkollegen zu aktualisieren und Daten einzuführen. Siehe Punkte 4 und 5.
4) Verwenden Sie ein Tool wie http://www.liquibase.org , um Upgrades in Ihrer Datenbankstruktur zu verwalten. Grund: Bietet Ihnen Flexibilität bei der Möglichkeit, die vorhandene Struktur zu ändern und in Versionen voranzukommen
5) Verwenden Sie ein Tool wie http://dbunit.sourceforge.net/ , um die Daten zu verwalten. Richten Sie Szenariodateien (XML oder XLS) für bestimmte Testfälle und Basisdaten ein und löschen Sie nur, was für einen Testfall erforderlich ist. Grund: Viel besser als das manuelle Einfügen und Löschen von Daten Grund 2: Für Tester ist es einfacher zu verstehen, wie Szenarien angepasst werden. Grund 3: Dies kann schneller ausgeführt werden
6) Sie benötigen Funktionstests, die auch DBUnit-ähnliche Szenariodaten enthalten. Dies sind jedoch weitaus größere Datenmengen, die das gesamte System ausführen. Damit ist der Schritt abgeschlossen, das Wissen zu kombinieren, dass a) die Komponententests ausgeführt werden und daher die Logik einwandfrei ist. B) dass die Integrationstests für die Datenbank ausgeführt werden und SQL korrekt ist, was dazu führt, dass "und das System als Ganzes als Top-to zusammenarbeitet" unterer Stapel "
Diese Kombination hat mir bisher gute Dienste geleistet, um eine hohe Qualität der Tests und Produkte zu erreichen sowie die Geschwindigkeit der Entwicklung von Komponententests und die Flexibilität bei Änderungen aufrechtzuerhalten.
quelle
Klingt so, als hätten Sie kulturelle Probleme bei der Arbeit, die Sie daran hindern, Ihre Arbeit in vollem Umfang und mit dem Nutzen Ihres Produkts zu erledigen. Vielleicht möchten Sie etwas dagegen tun.
Wenn Ihr Datenbankschema hingegen der Versionskontrolle unterliegt, können Sie jederzeit einen Testaufbau durchführen lassen, der eine Datenbank aus dem Schema erstellt, mit Testdaten füllt, Ihre Tests ausführt, die Ergebnisse sammelt und dann die Datenbank löscht. Es würde nur für die Dauer der Tests existieren. Es kann sich um eine neue Datenbank in einer vorhandenen Installation handeln, wenn Hardware ein Problem darstellt. Dies ähnelt dem, was wir dort tun, wo ich arbeite.
quelle
Wenn Sie Oracle bei der Arbeit verwenden, können Sie die Funktion "Wiederherstellungspunkt in Flashback-Datenbank" verwenden, um die Datenbank auf eine Zeit vor Ihren Tests zurückzusetzen. Dadurch werden alle Änderungen entfernt, die Sie persönlich an der DB vorgenommen haben.
Sehen:
https://docs.oracle.com/cd/E11882_01/backup.112/e10642/flashdb.htm#BRADV71000
Wenn Sie eine Testdatenbank für die Verwendung mit Oracle Production / Work benötigen, suchen Sie die XE Express Edition-Datenbank von Oracle. Dies ist für den persönlichen Gebrauch kostenlos, mit einer Datenbankbeschränkung von weniger als 2 GB.
quelle
Wir haben kürzlich zu JavaDB oder Derby gewechselt , um dies zu implementieren. Derby 10.5.1.1 implementiert jetzt eine In-Memory-Darstellung, sodass sie sehr schnell ausgeführt wird und nicht auf die Festplatte verschoben werden muss: Derby In Memory Primer
Wir entwickeln unsere Anwendung so, dass sie unter Oracle, PostgreSQL und Derby ausgeführt werden kann, damit wir auf keiner Plattform zu weit kommen, bevor wir feststellen, dass eine Datenbank eine Funktion unterstützt, die andere nicht unterstützen.
quelle
Ich bin mit Banjollity einverstanden. Das Einrichten isolierter Entwicklungs- und Testumgebungen sollte eine hohe Priorität haben. Jedes von mir verwendete Datenbanksystem ist entweder Open Source oder verfügt über eine kostenlose Entwicklerversion, die Sie auf Ihrer lokalen Workstation installieren können. Auf diese Weise können Sie mit demselben Datenbankdialekt wie die Produktion entwickeln, haben vollen Administratorzugriff auf Entwicklungsdatenbanken und sind schneller als mit einem Remote-Server.
quelle
Versuchen Sie, Derby zu verwenden . Es ist einfach und tragbar. Mit Hibernate wird Ihre App flexibel. Testen Sie auf Derby, Produktion auf alles, was Sie mögen und vertrauen.
quelle
Wir erstellen gerade eine Datenbanktestumgebung. Wir sind der Meinung, dass wir ein echtes Datenbankverwaltungssystem mit simulierten Daten verwenden müssen . Ein Problem mit einem simulierten DBMS ist, dass SQL als Standard nie wirklich vollständig geliert ist, sodass eine künstliche Testumgebung den Dialekt unserer Produktionsdatenbank genau unterstützen müsste. Ein weiteres Problem besteht darin, dass wir in großem Umfang Spaltenwertbeschränkungen, Fremdschlüsseleinschränkungen und eindeutige Einschränkungen verwenden. Da ein künstliches Tool diese wahrscheinlich nicht implementieren würde, könnten unsere Komponententests bestanden werden, aber unsere Systemtests würden fehlschlagen, wenn sie zum ersten Mal den Real treffen Einschränkungen. Wenn Tests zu lange dauern, deutet dies auf einen Implementierungsfehler hin und wir würden unsere Abfragen optimieren (normalerweise sind Testdatensätze im Vergleich zur Produktion winzig).
Wir haben auf jedem Entwicklercomputer und auf unserem Server für kontinuierliche Integration und Test (wir verwenden Hudson) ein echtes DBMS installiert. Ich weiß nicht, welche Einschränkungen Ihre Arbeitsrichtlinien haben, aber es ist ziemlich einfach, PostgreSQL, MySQL und Oracle XE zu installieren und zu verwenden. Diese sind alle für die Entwicklung kostenlos (sogar für Oracle XE), daher gibt es keinen vernünftigen Grund, ihre Verwendung zu verbieten.
Die entscheidende Frage ist, wie Sie sicherstellen können, dass Ihre Tests immer mit der Datenbank in einem konsistenten Zustand beginnen. Wenn die Tests alle schreibgeschützt waren, kein Problem. Wenn Sie Mutationstests so entwickeln könnten, dass sie immer in Transaktionen ausgeführt werden, die niemals festgeschrieben werden, ist dies kein Problem. In der Regel müssen Sie sich jedoch Gedanken über das Umkehren von Updates machen. Zu diesem Zweck können Sie den Ausgangszustand in eine Datei exportieren und nach dem Test wieder importieren (dies tun die Shell-Befehle exp und imp von Oracle). Oder Sie können einen Checkpoint / Rollback verwenden. Eine elegantere Möglichkeit ist jedoch die Verwendung eines Tools wie dbunit , das für uns gut funktioniert.
Der Hauptvorteil dabei ist, dass wir im Vorfeld viel mehr Fehler erkennen, die viel einfacher zu beheben sind und unsere realen Systemtests nicht blockiert werden, während Entwickler fieberhaft versuchen, Probleme zu beheben. Dies bedeutet, dass wir besseren Code schneller und mit weniger Aufwand produzieren.
quelle
Sie könnten HSQLDB für Speicher-DB-Tests verwenden. Das Starten der In-Memory-Datenbank und das Ausführen von Tests ist ziemlich einfach.
http://hsqldb.org/
quelle
jOOQ ist ein Tool, das nicht nur SQL-Abstraktion bietet, sondern auch kleine Tools wie ein SPI enthält, mit dem die gesamte JDBC verspottet werden kann. Dies kann auf zwei Arten funktionieren, wie in diesem Blog-Beitrag dokumentiert :
Durch die Implementierung des
MockDataProvider
SPI:// context contains the SQL string and bind variables, etc. MockDataProvider provider = context -> { // This defines the update counts, result sets, etc. // depending on the context above. return new MockResult[] { ... } };
In der obigen Implementierung können Sie jede SQL-Anweisung programmgesteuert abfangen und ein Ergebnis dafür zurückgeben, sogar dynamisch, indem Sie die SQL-Zeichenfolge "analysieren", um einige Prädikate / Tabelleninformationen usw. zu extrahieren.
Durch die Verwendung der einfacheren (aber weniger leistungsfähigen)
MockFileDatabase
... das ein Format wie das folgende hat (eine Reihe von Anweisungs- / Ergebnispaaren):
Die obige Datei kann dann wie folgt gelesen und verwendet werden:
import static java.lang.System.out; import java.sql.*; import org.jooq.tools.jdbc.*; public class Mocking { public static void main(String[] args) throws Exception { MockDataProvider db = new MockFileDatabase( Mocking.class.getResourceAsStream("/mocking.txt"); try (Connection c = new MockConnection(db)); Statement s = c.createStatement()) { out.println("Actors:"); out.println("-------"); try (ResultSet rs = s.executeQuery( "select first_name, last_name from actor")) { while (rs.next()) out.println(rs.getString(1) + " " + rs.getString(2)); } } } }
Beachten Sie, wie wir die JDBC-API direkt verwenden, ohne tatsächlich eine Verbindung zu einer Datenbank herzustellen.
Beachten Sie, dass ich für den Anbieter von jOOQ arbeite, daher ist diese Antwort voreingenommen.
Beachten Sie, dass Sie irgendwann eine gesamte Datenbank implementieren
Das Obige funktioniert für einfache Fälle. Beachten Sie jedoch, dass Sie möglicherweise eine gesamte Datenbank implementieren. Sie wollen:
OK, indem Sie die Datenbank wie oben gezeigt verspotten, können Sie die Syntax "überprüfen", da jede Syntax, die Sie in der oben aufgeführten exakten Version nicht vorausgesehen haben, von einem solchen Verspottungsansatz abgelehnt wird.
Sie können einen Parser implementieren, der SQL analysiert ( oder wiederum jOOQs verwendet ), und dann die SQL-Anweisung in etwas umwandeln, für das Sie leichter ein Ergebnis erkennen und erstellen können. Letztendlich bedeutet dies jedoch nur die Implementierung einer gesamten Datenbank.
Das macht die Sache noch schwieriger. Wenn Sie eine Einfügung ausführen und dann aktualisieren, unterscheidet sich das Ergebnis offensichtlich von zuerst aktualisieren und dann einfügen, da die Aktualisierung möglicherweise Auswirkungen auf die eingefügte Zeile hat oder nicht.
Wie stellen Sie sicher, dass dies passiert, wenn Sie eine Datenbank "verspotten"? Sie benötigen eine Zustandsmaschine, die sich den Zustand jeder "verspotteten" Tabelle merkt. Mit anderen Worten, Sie implementieren eine Datenbank.
Spott bringt dich nur so weit
Wie auch Piotrek erwähnt hat, bringt Sie das Verspotten nur so weit. Dies ist in einfachen Fällen hilfreich, wenn Sie nur einige sehr bekannte Abfragen abfangen müssen. Es ist unmöglich, wenn Sie die Datenbank für ein gesamtes System verspotten möchten. Verwenden Sie in diesem Fall eine tatsächliche Datenbank, im Idealfall dasselbe Produkt, das Sie in der Produktion verwenden.
quelle
Ich denke, mein Acolyte-Framework kann für ein solches DB-Modell verwendet werden: https://github.com/cchantep/acolyte .
Es ermöglicht das Ausführen von vorhandenem Java (zum Testen) mit Verbindungen, die Sie für die Abfrage- / Aktualisierungsbehandlung verwenden: Zurückgeben geeigneter Ergebnismengen, Aktualisierungsanzahl oder Warnung entsprechend den Ausführungsfällen.
quelle
Verwenden Sie zunächst eine ORM-Schicht für den DB-Zugriff?
Wenn nicht: Was Sie denken, nützt nichts. Was nützt das Testen, wenn Sie nicht sicher sind, ob SQL, das Sie starten, mit Ihrer Datenbank in der Produktion funktioniert, da Sie in Testfällen etwas anderes verwenden.
Wenn ja: Dann können Sie sich verschiedene Optionen ansehen, auf die hingewiesen wird.
quelle