2.2. Funktionsweise

Dieser Abschnitt beschreibt die Funktionsweise von checkerberry db anhand der drei Test-Phasen die in Abschnitt 1.3.3.1, „Test-Ablauf“ beschrieben sind.

In den Code-Beispielen werden in der Regel die Spezifika der konkreten Testframeworks JUnit3, JUnit4 oder TestNG nicht aufgeführt, da sie in den meisten Fällen für das Verständnis des Beispiels nicht benötigt werden.

2.2.1. Setup-Phase

Checkerberry db wird eingesetzt, um Funktionen mit einer integrierten Datenbank zu testen. Generell benötigen Tests einen klar definierten Eingabezustand, um nach der Durchführung der zu testenden Komponente den erwarteten Ergebniszustand prüfen zu können. Im Fall von integrierten Datenbanktests bedeutet dies, dass der Inhalt der Datenbank vor dem Test in einen definierten Zustand versetzt werden muss. Zu diesem Zweck spielt checkerberry db in der Setup-Phase initiale Testdaten in die Datenbank ein.

Bevor initiale Testdaten in die Datenbank eingespielt werden können, muss checkerberry db die einzuspielenden Testdaten ermitteln. Die Definition der Testdaten erfolgt über XML-Dateien. Der Name der Datei ergibt sich implizit aus dem Namen der Testklasse und dem Namen der Testmethode: <Name der Testklasse>_<Name der Testmethode>_initial.xml z.B. UserDaoTest_testInsertUser_initial.xml. Die Ermittlung der Namen der Testdaten ist konfigurierbar (siehe Abschnitt 2.4.18, „Namenskonvention der XML-Testdaten anpassen“).

Die Testdaten werden im Klassenpfad, an der gleichen Stelle wie die zugehörige Testklasse gesucht.

Beispiel 2.1. Beispiel UserDaoTest.testInsertUser

package de.conceptpeople.sample.dao;

public class UserDaoTest extends AbstractSampleTestCase {

  /**
   * Testet das Anlegen eines neuen Users.
   * @throws Exception wenn der Test fehlschlug.
   */
  public void testInsertUser() throws Exception {
    // Neues User-Objekt erzeugen…
    User user = new User("Homer", "Simpson", "16.09.1946");
    // …und in der Datenbank speichern.
    boolean success = dao.save(user);
    // Prüfen über JUnit-Methode, ob das Speichern erfolgreich war.
    assertTrue(success);

    // Testhandler aus der Umgebung holen.
    DbTestHandler testHandler = getEnvironment().getTestHandler();

    // Die initialen Daten dürfen sich nicht geändert haben.
    testHandler.assertInitialDataUnchanged();
    // Der Datenbankinhalt muss die erwarteten Daten beinhalten.
    testHandler.assertEqualsExpected();
}


In obigen Code-Beispiel ist die Testklasse UserDaoTest dargestellt. Bei der Durchführung der Setup-Phase für die Testmethode testInsertUser werden die initialen Testdaten aufgrund von Klassen- und Methodenname in der Datei UserDaoTest_testInsertUser_initial.xml gesucht.

Abbildung 2.2. Screenshot - Testdaten im Klassenpfad

Screenshot - Testdaten im Klassenpfad


Aufgrund der Package-Spezifikation de.conceptpeople.sample.dao wird die Klasse für UserDaoTest bei der Kompilierung in dem Unterverzeichnis de/conceptpeople/sample/dao des Klassenpfads erstellt. In diesem Unterverzeichnis werden auch die Testdaten gesucht. In dem aktuellen Beispiel sind die Testdaten in der Datei UserDaoTest_testInsertUser_initial.xml definiert.

Beispiel 2.2. Beispiel UserDaoTest_testInsertUser_initial.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE dataset PUBLIC "-//ConceptPeople//DTD sample-db 1.0//EN"
  "../sample-db.dtd">

<dataset>
  <USERS NAME="Bart" SURNAME="Simpson" BIRTHDATE="2009-03-18"/>
  <USERS NAME="Lisa" SURNAME="Simpson" BIRTHDATE="2009-03-18"/>
  <USERS NAME="Maggie" SURNAME="Simpson" BIRTHDATE="2009-03-18"/>
  <USERS NAME="Marge" SURNAME="Simpson" BIRTHDATE="2009-03-18"/>
</dataset>


Das oben angegebene Beispiel enthält eine Testdatendatei. Die Testdaten werden unter dem Tag dataset definiert. Innerhalb dieses Tags werden die einzuspielenden Datensätze angegeben. In dem obigen Beispiel werden vier Datensätze in die Datenbanktabelle USERS eingespielt. Zu diesem Zweck sind in den Testdaten vier USERS-Tags definiert, die die Werte der Spalten NAME, SURNAME und BIRTHDATE enthalten.

In vielen Situationen verwenden unterschiedliche Testmethoden einer Testklasse die gleichen initialen Testdaten. In diesen Situationen ist es sinnvoll, die Testdaten nicht auf Methoden-, sondern auf Klassenebene zu definieren. Für das obige Beispiel können die Testdaten somit ebenfalls in der Datei UserDaoTest_initial.xml gespeichert werden. Die Suche der initialen Testdaten erfolgt in checkerberry db in zwei Schritten: Zunächst werden die Testdaten auf Methodenebene unter dem Namen UserDaoTest_testInsertUser_initial.xml gesucht. Wenn diese Datei nicht vorhanden ist, werden die Testdaten auf Klassenebene unter dem Namen UserDaoTest_initial.xml gesucht.

Dieses Konzept minimiert den Verwaltungsaufwand und wird unter dem Namen „Convention over Configuration“ in vielen Frameworks angewendet. Im konkreten Fall von checkerberry db ist nahezu kein Verwaltungsaufwand für das Einspielen der Testdaten erforderlich. Natürlich muss der Software-Entwickler die initialen Testdaten definieren. Diese Aufgabe ist jedoch in jedem Fall erforderlich. Das Testframework kann lediglich dafür Sorge tragen, dass das Einbinden der Testdaten keinen großen Aufwand erzeugt.

Wenn checkerberry db initiale Testdaten findet, wird zunächst der Inhalt aller Tabellen in der Datenbank gelöscht. Danach werden die gefundenen Testdaten in die Datenbank eingespielt. Wenn keine Testdaten gefunden werden, bleibt der Inhalt der Datenbank unverändert.

Das checkerberry test center stellt einen Caching-Mechanismus zur Verfügung, der das überflüssige Löschen und Einspielen von Tabellen verhindert. Die Funktionsweise des Caches ist in Abschnitt 2.4.14, „Performance-Optimierung durch Caching von Tabellen“ beschrieben. Darüber hinaus besteht auch die Möglichkeit, Tabellen vollständig aus der Verwendung von checkerberry db auszuschließen. Dies kann z.B. bei temporären Tabellen sinnvoll sein. Dieses Feature ist unter Abschnitt 2.4.6, „Ignorieren von Datenbanktabellen“ beschrieben.

Checkerberry db bietet einige Features, um das Löschen der gesamten Datenbanktabellen in der Setup-Phase zu umgehen (siehe Abschnitt 2.4.16, „Einspielen von Testdaten temporär unterdrücken“).