# JUnit-Log auslesen



## Twaldigas (6. Mai 2011)

Guten Tag Java-Community,

ich arbeite zur Zeit mit JUnit und über Eclipse hat man ja eine schöne Oberfläche auf der man sieht, welche Tests erfolgreich durchgeführt wurden und welche nicht. Außerdem sieht man ja im Log, wenn ein Test fehlgeschlagen ist, warum. Nun möchte ich genau diese Informationen, die mir dort ausgegeben werden, auslesen und mit Java in eine Datenbank schreiben. Leider habe ich keinen Weg gefunden, wie man das bewerkstelligen kann. 

Dass man die Informationen via Ant als HTML-Report ausgeben kann, weiß ich. Ich möchte die Informationen aber in einer Datenbank stehen haben, um mit ihnen weiter arbeiten zu können.

Ich hoffe, dass Ihr mir da vielleicht weiter helfen könnt.

Gruß Twaldigas


----------



## Guardi (6. Mai 2011)

Ich hatte dafür mal eine abstrakte Klasse mit folgender Methode gebaut:


```
@Test
	public void testRun() throws Exception{
		
		try {
			runTestImpl();
		} catch (Exception e) {
			logger.error(e.getLocalizedMessage());
			throw e;
		}
		  catch(AssertionError e){
			  logger.error(e.getLocalizedMessage());
			  throw e;
		  }
		  
		  logger.info("SUCCESS");
	}

public abstract void runTestImpl() throws Exception;
```

runTestImpl muss dann einfach nach Wünschen überschrieben werden.
Ich hab die abstrakte Klasse unter anderem noch dazu genutzt externe Konfigurationen zu laden und zu setzen, die sich auf alle Tests beziehen.

edit: Das ist natürlich ein allgemeiner Hinweis. Anstatt eines Loggers kannst du die Daten ja irgendwo sonst speichern.


----------



## FArt (6. Mai 2011)

Ich frage mich wofür man das braucht.

Sinnvoll ist es z.B. bei einem NightlyBuild oder CI... aber dafür gibt es fertige Tools, die das ganze auch noch schön aufbereiten, z.B. Jenkins, ...


----------



## Guardi (6. Mai 2011)

Ich habs definitiv gebraucht.
Allerdings hatte der Logger bei mir vielfältige Aufgaben.
Ich habe einen TestAutomaten entwickelt der neben den blossen Testergebnissen verschiedene Ereignisse usw. mitloggen sollte, da der TestAutomat permanent mit anderen TestDaten gefüttert wurde.


----------



## maki (6. Mai 2011)

Logging mit einem Logger in Tests ist in 99% der Fälle Blödsinn.
Entweder ein Test geht durch, oder es schlägt fehl (mit Meldung). Alles andere ist Quatsch.

Der TS will kein Logging, er will die Ergebnisse der Tests, je nachdem wie die TEsts aufgeführt werden (Maven, Ant, Manuell) werden solche Reports erstellt, oder eben nicht.
Wie startet der TS denn seine Tests?


----------



## FArt (6. Mai 2011)

Guardi hat gesagt.:


> Ich habs definitiv gebraucht.
> Allerdings hatte der Logger bei mir vielfältige Aufgaben.
> Ich habe einen TestAutomaten entwickelt der neben den blossen Testergebnissen verschiedene Ereignisse usw. mitloggen sollte, da der TestAutomat permanent mit anderen TestDaten gefüttert wurde.



Hört sich m.E. noch seltsamer an... ein Logger mit vielfältigen Aufgaben (separation of concerns?) ... Tests mit permanent andere Testdaten (sind die denn deterministisch?)... 
*grübel*

Das kann ich doch ohne große Implementierung mit einem CI Tool erreichen, oder was kann der TestAutomat besonderes, was ihn einzigartig macht?


----------



## Twaldigas (6. Mai 2011)

@FArt
Genau für so etwas brauche ich das auch. Aber jetzt wohl nicht mehr, denn du hast mir ja ein schönes Beispiel (Jenkins) genannt, welches ich sogar schon kenne, aber vergessen hatte. DANKE!

@Guardi
Vielen Dank für den Quelltext. Auch wenn ich es jetzt erst einmal mit einem Tool versuchen werde, so werden ich für diesen Quelltext bestimmt eine Einsatzmöglichkeit finden. Vielleicht gefallen mir die vorhandenen Tools ja auch nicht und dann entwickle ich halt doch mein eigenes.

Vielen Dank an euch beide für die schnelle Antwort. Noch einen schönen Freitag und ein entspanntes Wochenende wünsche ich euch.


----------



## Guardi (6. Mai 2011)

FArt hat gesagt.:


> Hört sich m.E. noch seltsamer an... ein Logger mit vielfältigen Aufgaben (separation of concerns?) ... Tests mit permanent andere Testdaten (sind die denn deterministisch?)...
> *grübel*
> 
> Das kann ich doch ohne große Implementierung mit einem CI Tool erreichen, oder was kann der TestAutomat besonderes, was ihn einzigartig macht?



Es geht um step-by-step Testen von WebOberflächen, Details erspare ich mir an dieser Stelle.
Und bekanntermaßen gibt es in einer Web-Oberfläche oft unterschiedliche Wege zum Ziel, verschiedene Sprachversionen, unterschiedliche Rollen etc etc.
Willst du dafür überall redundanten Code schreiben? Also ich nicht.

Nun sagt mir der Stacktrace einer Exception aber zu wenig aus um die Ursache und den Punkt des Problems wirklich zu finden. Außerdem sind solche Tests nicht reine Entwickler-Tests und sollen deswegen einfach besser lesbar sein.


----------



## maki (6. Mai 2011)

> Außerdem sind solche Tests nicht reine Entwickler-Tests und sollen deswegen einfach besser lesbar sein.


Wenn Logausgaben wichtig für das Ergebniss eines Tests sind, sind es keine automatisierten Tests, solange die Logausgaben auch nicht automatisiert geparst werden 

JUnit ist für autom. Tests gedacht, die müssen selbstständig, ohne zus. "Menschen" feststellen können ob etwas geht oder nicht.


----------



## FArt (6. Mai 2011)

Guardi hat gesagt.:


> Es geht um step-by-step Testen von WebOberflächen, Details erspare ich mir an dieser Stelle.
> Und bekanntermaßen gibt es in einer Web-Oberfläche oft unterschiedliche Wege zum Ziel, verschiedene Sprachversionen, unterschiedliche Rollen etc etc.
> Willst du dafür überall redundanten Code schreiben? Also ich nicht.
> 
> Nun sagt mir der Stacktrace einer Exception aber zu wenig aus um die Ursache und den Punkt des Problems wirklich zu finden. Außerdem sind solche Tests nicht reine Entwickler-Tests und sollen deswegen einfach besser lesbar sein.



Wieso redundanter Code? Ich verstehe das Problem bzw. den Bedarf nicht. Kann sein, dass bei euch der Bedarf dafür gegeben ist, aber die Begründungen hören sich alle nach suboptimalem Design an.

Mehr intensives Unit-Testing erspart in der Regel viel Aufwand für so großartig angelegte Integrationstest. Und dann hat auch Maki Recht, denn bei solchen Tests kann man oft auf Logfiles verzichten. Hilfreich sind sie aber allemal bei (aus Versehen) nicht deterministische Tests ;-)

Aber egal.. wir schweifen ab... der TS ist zufrieden


----------



## mvitz (7. Mai 2011)

Ansonsten ginge auch so etwas:


```
package de.mvitz.examples.junit;

import org.junit.Rule;
import org.junit.rules.MethodRule;
import org.junit.rules.TestWatchman;
import org.junit.runners.model.FrameworkMethod;

public abstract class AbstractLoggingBaseTest {
    @Rule
    public MethodRule watchman = new TestWatchman() {
        @Override
        public void succeeded(FrameworkMethod aMethod) {
            System.out.print(".");
        }

        @Override
        public void failed(Throwable aE, FrameworkMethod aMethod) {
            System.out.print("E");
        }
    };
}
```


```
package de.mvitz.examples.junit.rules;

import static org.junit.Assert.fail;
import org.junit.Test;
import de.mvitz.examples.junit.AbstractLoggingBaseTest;

public class MethodRuleTest extends AbstractLoggingBaseTest {
    @Test
    public void failingTest() throws Exception {
        fail();
    }
    @Test
    public void passingTest() throws Exception {
    }
}
```

Natürlich die Sysouts dann durch einen anderen Aufruf ersetzen.


----------



## FArt (7. Mai 2011)

mvitz hat gesagt.:


> Ansonsten ginge auch so etwas:
> 
> 
> ```
> ...



Obiges Beispiel hat einige Nachteile:
Erfolg und Misserfolg müssen explizit aufgerufen werden (hast du auch vergessen) und wenn du nicht Throwable fängst, gehen dir auch noch Informationen durch die Lappen.

Es hätte mich gewundert, wenn es dafür nicht eine Standardlösung gegebnen hätte: RunListener (JUnit API)


----------



## mvitz (7. Mai 2011)

Ich verstehe deine Aussage nicht:

1) Erfolg und Misserfolg müssen explizit aufgerufen werden (hast du auch vergessen)
Wo muss was aufgerufen werden? Die beiden Methoden succeeded und failed werden automatisch nach jedem Test aufgerufen (durch das JUnit Framework).

2) und wenn du nicht Throwable fängst, gehen dir auch noch Informationen durch die Lappen.
Wo muss ich Throwable fangen? Im Test mit Sicherheit nicht, denn eine unerwartete Exception --> failed (auch ein fehlgeschlagenes Assert ist "nur" eine Exception). In der failed Methode muss ich auch nichts catchen, kann aber über den Throwable Parameter auf die Exception zugreifen.


----------



## FArt (9. Mai 2011)

mvitz hat gesagt.:


> Ich verstehe deine Aussage nicht:
> 
> 1) Erfolg und Misserfolg müssen explizit aufgerufen werden (hast du auch vergessen)
> Wo muss was aufgerufen werden? Die beiden Methoden succeeded und failed werden automatisch nach jedem Test aufgerufen (durch das JUnit Framework).
> ...



Da hast du Recht. Ich habe die @Rule Annotation übersehen.


----------

