
- Lege Testklassen im selben Verzeichnis ab, in dem sich auch die Produktionsklassen befinden.

- Deswegen war es einfacher, die Testklassen in einem separaten aber analog aufgebauten Verzeichnisbaum abzulegen.

Auf dem Klassenpfad

Auf zu neuen Ufern: Hallo Jigsaw, hallo Java Module!

Module com.xyz

- Das Module namens
com.xyz
enthält ein paar ausgedachte Einträge. - Es enthält die Pakete
com.abc
undcom.xyz
. - Es exportiert einzig und allein das Paket
com.xyz
.

Hinweis: Das Paket com.abc sollte nicht in einem Modul namens com.xyz auftauchen. Warum nicht? Stephen erläutert in seinem Blog JPMS module naming die Details.
Module black.box

- Das Testmodul black.box benötigt das Modul com.xyz sowie eine Reihe anderer Module rund ums Testen.
- Es kann dabei nur auf zugreifbare Typen in diesen anderen Modulen zugreifen (nämlich solche, die mit public versehen sind und sich gleichzeitig in einem exportierten Paket befinden).
- Das gilt natürlich ebenso für unser com.xyz-Modul: Tests können auf öffentliche Klassen im Paket com.xyz zugreifen – nicht aber auf Klassen im geschützten Paket com.abc, selbst wenn diese public sind.
- Zusätzlich erlaubt das black.box-Modul mittels open tiefe Reflexion, damit Testframeworks auch Package-Private-Tests auffinden und ausführen können.

Black-Box-Testen ist allerdings der einfache Teil der Geschichte. Das black.box
-Testmodul ist quasi der erste Kunde des Hauptmoduls com.xyz
. Das Testmodul hält sich an die vom Modulsystem vorgegebenen Grenzen – so wie jedes andere Modul auch.
Es folgt der spannende Teil.
Modular White Box Testing
Zunächst erweitern wir die Zugriffstabelle um eine Spalte. Nämlich um eine Spalte, welche die Zugriffsmöglichkeiten aus einem fremden Modul beschreibt.
Zugriffstabelle
Die Klasse A in package foo enthält jeweils ein Feld für jeden Zugriffsmodifikator. Jede Spalte von B bis F steht für eine andere Klasse und zeigt die Sichtbarkeit an: Ein ✅ bedeutet, dass das entsprechende Feld von A sichtbar ist; ein ❌ steht für “nicht sichtbar”.
- B – gleiches module, gleiches package, andere Datei: package foo; class B {}
- C – gleiches module, anderes package, Ableitung: package bar; class C extends foo.A {}
- D – gleiches module, anderes package, beziehungslos: package bar; class D {}
- E – anderes module, package foo wird exportiert: package bar; class E {}
- F – anderes module, package foo wird nicht exportiert package bar; class F {}


Zurück zum classpath
Alle module-info.java-Dateien löschen, oder diese zumindest vom Kompilieren ausschließen – und schon ignorieren die Tests die Grenzen des Modulsystems! Dadurch werden, neben internen Details von Java selbst, auch Interna von anderen und eben der eigenen Bibliothek verfügbar. Letzteres war das Ziel – doch die Kosten, es zu erreichen, sind hoch.
Wie aber können wir die Grenzen des Modulsystems intakt lassen und trotzdem die internen Typen der eigenen Bibliothek testen? Dazu mehr in den nächsten zwei Abschnitten.
Modular White Box Testing mit module-info.java in src/test/java
Die für den Testautor einfachste Variante besteht darin, eine Beschreibung für ein Testmodul anzulegen. Die Beschreibung kann mit der gleichen Syntax geschehen, die bei normalen Modulen eingesetzt wird:
So kann ein Testmodul aussehen
Dabei wird es in zwei logische Abschnitte geteilt:
- Kopie aller Direktiven aus dem Hauptmodul
- Zusätzliche Direktiven für das Testen

Notiz: Das Kopieren von Direktiven aus dem Hauptmodul is natürlich etwas mühselig und fehleranfällig. Das Java-Build-Tool Pro automatisiert diesen Schritt und erlaubt es ausschließlich die zusätzlichen Direktiven fürs Testen anzugeben.
White Box Modular Testing with extra Java command line options
Neben der gerade beschriebenen Variante eines dediziertem Testmoduls, kann man auch mittels java Kommandozeilenparameter ans Ziel kommen. Man konfiguriert so das Modulsystem quasi beim Starten der JVM. Die meisten Build-Tools unterstützen die Angabe solcher java Kommandozeilen-Parameter beim Starten eines Testlaufs.
Um obiges Testmodul mittels Java nachzubauen, braucht es folgende Parameter:

- Wie organisiert man nun Tests in modularen Projekten?
Es ist in meine Augen notwendig, dass sowohl Black Box als auch White Box Tests geschrieben und ausgeführt werden. Das micromata/sawdust-Projekt zeigt eine mögliche Struktur:

Dazu kommt noch, dass man das Verhalten seines Moduls sowohl auf class-path als auch module-path testen sollte.
Die englische Textversion dieses Blogbeitrags gibt es hier.