# Test-Code in Java-Klassen verstecken (wie mit Precompiler möglich)



## Klaus (16. Okt 2009)

Hi,
und zwar müssen wir Code schreiben, der sehr sehr gut getestet werden soll mit entsprechenden Testcases. Am Ende werden wir erheblich mehr Testcode als wirklichen Code haben.

Nun ist die Frage, wie man Testcode elegant in Java-Klassen einbetten kann.

Was ich damit meine:
Wir würden unsere Testfälle gerne im "JUnit-Format" schreiben (JUnit3, 4 geht leider nicht), so dass wir am Ende mit einem Klick alle Testfälle durchlaufen können. Das Problem ist nun aber ein wenig, dass unsere Klassen/Methoden relativ viel vor dem Benutzer verstecken, da ist es aber dann schwierig, diese internen Methoden zu testen.

Bevor nun der Aufschrei kommt: Es handelt sich um einen Emulator der um bestimmte Funktionalität erweitert werden soll. Deswegen sind manche Methoden von außen überhaupt nicht zugreifbar, werden aber vom emulierten Code (über teilweise mehrere Umwege) aufgerufen.


Eine Möglichkeit wäre es, nun statt einer extra Klasse für den Testfall die Testfälle innerhalb der zu testenden Klasse zu haben.

Also irgendetwas wie:

```
class TesteMich {
  private int zuTestendeMethode() {
  //...
  }

  //Testcases
  public void test_Testfall1() {
  //Teste zuTestendeMethode
  }
}
```

Würde vom Prinzip gehen, wäre aber in meinen Augen doch unschön. Zum einen würde es die Klasse umgemein aufblähen (da mehr Testcode als echter Code) und zum zweiten, wenn man ein TestMich Objekt hat, würde man die Methode test_Testfall1 (und Testfall2, 3, ...) sehen.

Nun ist meine Frage: Wie löst man das elegant?

In C/C++/C# konnte man schön auf den Precompiler zurück greifen, und dann z.B. soetwas schreiben:

```
class TesteMich {
  private int zuTestendeMethode() {
  //...
  }

  #ifdef TESTRUN
  //Testcases
  public void test_Testfall1() {
  //Teste zuTestendeMethode
  }
  #endif
}
```


Oder

```
class TesteMich {
#ifdef TESTRUN
  #define PRIVATEACC public
#else
  #define PRIVATEACC private
#endif
   PRIVATEACC int zuTestendeMethode() {
  //...
  }
}
```
So dass man mit entsprechenden Flags zwischen Testcode und Produktivcode (der kein Testcode enthält) entscheiden konnte.

Soweit ich es nun in Erfarung bringen konnte, geht das in Java leider nicht 

Wäre wirklich dankbar, wenn mir dort jemand weiterhelfen könnte. Schön wäre es, wenn z.B. alle private/protected Methoden/Variablen für die Testcases public wären und/oder ich Code einfüge, der ein public Interface für bestimmte Methoden anbietet, wenn die Testfälle am laufen sind.

Also soetwas in der Art:

```
class TesteMich {
  private int zuTestendeMethode() {
  //...
  }

  #Wenn Testlauf / kein Testlauf flag gesetzt ist dann zeige folgende Methode an:
  public int test_zuTestendeMethode() {
     return zuTestendeMethode();
  }
  #endif
}
```

So dass dann die Testfälle an entsprechend notwendigen stellen auf test_zuTestendeMethode() anstatt auf zuTestendeMethode() zurückgreifen.


Vielen Dank für jede Hilfe.

Klaus


----------



## Nader (16. Okt 2009)

Precompiler gibt nicht in Java. Einiges lässt sich aber doch mit Hilfe der Java Annotation realsieren, allerdingst müsste man dann einen eigenen Compiler und IDE entwickeln, um alle deine Anforderungen zu erfüllen.


----------



## FArt (16. Okt 2009)

Das ist m.E. nicht sinnvoll.

Ob private Methoden getestet werden müssen oder nicht, wurde bereits reichlich ausgebreitet. Wenn nötig, kann man das über Reflection erledigen. In der Regel reicht ein indirektes Testen über ihre verwendenden Methoden.


----------



## tfa (16. Okt 2009)

Dieses Problem haben wir vor einiger Zeit mal diskutiert.

http://www.java-forum.org/allgemeine-java-themen/69209-unit-tests-fuer-private-methoden.html

Ich bin auch der Meinung, nur die veröffentlichte Schnittstelle der Klassen zu testen. Alles andere geschieht indirekt. Ggf. müsst du dir eben eine passende Testumgebung zurechtmocken.



> [Precompiler] Soweit ich es nun in Erfarung bringen konnte, geht das in Java leider nicht


Ja, und dafür kann man nur dankbar sein.


----------



## skittish (16. Okt 2009)

> Bevor nun der Aufschrei kommt: Es handelt sich um einen Emulator der um bestimmte Funktionalität erweitert werden soll. Deswegen sind manche Methoden von außen überhaupt nicht zugreifbar, werden aber vom emulierten Code (über teilweise mehrere Umwege) aufgerufen.


Verstehe hier das Problem nicht.
- was ist an einem Emulator so besonderes?
- wenn der Emulator Code über Umwege aufrufen kann, warum kann dies ein Unit Test nicht?

Grundsätzlich sehe ich dies so:
Protected Methoden sind so zu testen, wie sie auch vom Benutzern verwendet werden. (Kein Problem)

Über den Sinn von privaten Methoden, und dem diese testen zu wollen, mag man sich streiten. Mit JUnit wird es da auch unschön, weil JUnit für Blackbox Tests konzepiert wurde. Man testet nicht wie die Klasse arbeitet, sondern nur das die Klasse das erfüllt, was von außen gefordert ist. Und wenn sie das tut, dann ist auch sichergestellt, dass die privaten Methoden ihren Zweck erfüllen.

Damit ich jetzt nicht nur aufschreie, gebe ich hier noch das Stichwort _Reflection_ und _nested Classes_. Wobei man die Wahl hat zwischen aufwändigen Testcode und Mischung von Testcodes & Produktivcode.
Im Zweifel würde ich persönlich diese Precompiler Funktionalität kurz selber schreiben. Kleines Script, welches eingebettete Klassen mit einer bestimmten Annotation (z.B. @TestingPurpose) aus dem Code entfernt.


----------



## maki (16. Okt 2009)

> Nun ist die Frage, wie man Testcode elegant in Java-Klassen einbetten kann.


Gar nicht 

Der Rest wurde ja schon gesagt.


----------



## Klaus (16. Okt 2009)

Hallo,
okay vielen Dank für eure Antworten.


> > [Precompiler] Soweit ich es nun in Erfarung bringen konnte, geht das in Java leider nicht
> 
> 
> Ja, und dafür kann man nur dankbar sein.


Nicht wirklich.  Oder man sollte zumindest bedingtes Compilieren erlauben wie es bei C# der Fall ist.


Also:
Der Emulator lädt Code, angestoßen durch Emulator.load('meinProgramm'). Intern wird dann das Programm geladen, die Befehle in dem Programm nacheinander eingelesen, dekodiert und ausgeführt. Nun gibt es einige geschütze Methoden, zum Beispiel das Speichermanagement, die essentiell zum Ausführen des Programm sind. Das heißt, das Programm führt irgendeinen Befehl aus, z.B. speichere in Adresse X folgenden Wert, dies wird vom Emulator dekodiert, die Abhandlung des Befehls wird an eine geschützte Methode weitergereicht und die ruft dann irgendwann eine private/protected Methode auf, um im virtuellen Speicher des Emulator den Wert abzulegen, wobei diese Methode noch diverse Überprüfungen, Address-Mappings etc. durchführen muss.
Alle involvierten Methoden, mit Außnahme von Emulator.load() sind protected oder private, da diese für den Entwicklung des Emulators nicht relevant sind bzw. nicht sichtbar sein sollen/dürfen.

Nun ist die Frage, wie man das testet. 
Dieses mittels speziellen emulierten Programmen zu testen ist sehr schwierig bzw. fast unmöglich, da das ganze Address-Handling gegenüber dem Programm transparent geschehen soll. Sprich, das Programm sieht höchstens: Wert wurde in X gespeichert oder nicht. Ob es nun intern wirklich richtig abgespeichert wurde oder nicht ist nicht erkennbar. Insbesondere kann man so nicht auf ungültige Parameter testen, da der vorgegeben Compiler dieses meist abfängt. Später müssen die internen Methoden aber auch ungültige Parameter erkennen und abfangen. Also würde noch dazu kommen, dass man den Compiler manipuliert bzw. das ganze auf Maschinencodeebene schreibt.

Besonders schwierig wirds, wenn bestimmte Methoden nicht vom Programm direkt ausgeführt werden können, aber bei vielen anderen Befehlen involviert ist und die Testprogramme nur über solche Befehle erahnen können, ob die zugrundliegenden Funktionen auch wirklich korrekt implementiert sind. Da auch mehrere Programme gleichzeitig emuliert/ausgeführt werden sollen, ist das Funktionieren eines Befehls im Programm nur ein schlechter Indikator, ob denn alles korrekt implementiert wurde (Synchronisationsfehler usw.).


Wenn man stattdessen die Methoden in den Testfällen direkt ansprechen könnte, würde dieses vieles erheblich leichter machen und man müsste nicht den Umweg Testprogramm -> Compiler -> Methode_Zur_Befehlsabhandlung -> zuTestendeMethode gehen. Die Testfälle wären nicht nur erheblich leichter zu schreiben, sondern auch die Sicherheit, dass beim Ausführen/Emulieren von Programm nichts schief geht wäre deutlich höher. 

So wie es aussieht, wird wohl (leider) Testcode mit in der Klasse landen müssen, die evt. mit der Annotation @TestingPurpose versehen werden (um behaupten zu können, dass man mit einem Precompiler es später entfernen könnte ).  Aber wie könnte so ein Precompiler aussehen, ist das sehr schwierig zu programmieren oder kann man auf Java Funktionen zurückgreifen?


----------



## maki (16. Okt 2009)

Precompiler & bedingte Kompilierung sind beides Dinge die es zum Glück (oder war es Absicht? ) in Java nicht gibt 

Wie man private Methoden testet steht in TFAs link, dasss das sog. "White Box" Tests sind und damit fragil, d.h. sehr anfällig für Änderungen.
Wenn das zu testende Subjekt eine einigermassen gute Struktur hat, kann man sehr leicht testen, sehe immer noch keinen Grund für einen Precompiler, bedingte Kompilierung oder gar tests in den zu testenden Klassen.

Mock Objekte sagen dir etwas? (JMOck, EasyMock, Mockito), etc. pp.)


----------



## skittish (17. Okt 2009)

Klaus hat gesagt.:


> Alle involvierten Methoden, mit Außnahme von Emulator.load() sind protected oder private, da diese für den Entwicklung des Emulators nicht relevant sind bzw. nicht sichtbar sein sollen/dürfen.


Hier sei nochmal angemerkt, dass protected garkein Problem darstellt. Eine nested Class, welche als delegate fungiert reicht aus.
Einfach gesagt, eine abgeleitete Klasse erstellen mit einer public Methode, welche nichts anderes macht als die protected Methode aufruft.

Wenn überhaupt sind private Methoden das Übel ...


----------



## maki (17. Okt 2009)

skittish hat gesagt.:


> Hier sei nochmal angemerkt, dass protected garkein Problem darstellt. Eine nested Class, welche als delegate fungiert reicht aus.
> Einfach gesagt, eine abgeleitete Klasse erstellen mit einer public Methode, welche nichts anderes macht als die protected Methode aufruft.
> 
> Wenn überhaupt sind private Methoden das Übel ...


Protected lässt sich doch einfacher testen: Einfach im selben Package die Testklasse ablegen wie die zu testende protected Methode, am besten in einem eigenen src Folder mit der gleichen package Strucktur (wie mit Maven2), dann brauchts auch kein Delegate 

Private zu testen ist imho der falsche Weg...


----------



## JanHH (18. Okt 2009)

Wenn man unbedingt will kann man allerdings sicher auch seinen java-Code vor dem kompilieren durch einen Präprozessor jagen. C++-Compiler kann man normalerweise auch in einem "nur Präprozessor"-Modus starten, diese also quasi für java Zweckentfremden, und mit dem guten alten make in Verbindung mit gcc kann man dann sicherlich auch für java-Projekte einen build-Prozess, der mit Präprozessor arbeitet, implementieren. Ob das nun eine gute Lösung ist, ist eine andere Frage.

Oder man schreibt im Quellcode über und unter den Bereichen, wo die Testfunktionen stehen, eindeutige Identifier in Kommentare, also z.B.

// BEGIN_TEST

Testfunktionen..

// END_TEST

und schreibt sich ein kleines Program, welches automatisch in allen Quellcodedateien, die zum Projekt gehören, die Testfunktionen ein- bzw. auskommentiert. Das wäre wohl die Lösung, die ich wählen würde. So ein Programm ist ja ruckzuck geschrieben, und dann braucht es nur einen java-Aufruf per Kommandozeile, um alle Testfunktionen im Projekt zu (de-)aktivieren.


----------

