# JUnit 4 User Interaktion



## KoenigGunther (13. Jul 2007)

Hi!
Ich frage mich ob es möglich ist einfache Programme die in der main-Methode laufen auch per UnitTests zu überprüfen.
Beispielsweise (ja, das ist ein sehr einfaches Beispiel) sollen Zufallszahlen generiert werden. Dazu soll der User eine Ober- und eine Unterschranke auf der Konsole eingeben. Eine Zufallszahl in dem Bereich wird generiert und auf der Konsole wieder ausgegeben. Überprüft soll werden, ob diese Zahl beispielsweise wirklich innerhalb er Schranken liegt.

Dabei ist es mir nicht wichtig dass da wirklich ein User vor sitzt, viel interessanter wäre es wenn ich das Automatisieren könnte, den User also simuliere, wie er immer mal wieder (aber endlich oft) zwei Zahlen eingibt und deren von JunitTests überprüftes Ergebnis auf der Konsole ausgibt.
Dabei wäre dann auch die Konsolenausgabe egal 

Hauptsächlich frage ich mich ob ich das mit JUnit hinbekomme Eingaben so zu generieren dass sie verwendet werden, als würden sie über die Konsole eingelesen.

Oh Mann - echt schwer zu beschreiben


----------



## KoenigGunther (17. Jul 2007)

Hm, vielleicht zu umständlich beschrieben?
Nochmal vielleicht etwas anders:

Gegeben ein Programm X dass meinetwegen 2x von der Konsole Usereingaben einliest... - Kann man dieses Programm mit Unit-Tests testen und die Eingaben des Users simulieren? Wenn ja, wie?

Oder wisst ihr wo ich sonst fragen könnte?

Der Christian...


----------



## HoaX (17. Jul 2007)

wenn dein progamm richtig aufgebaut ist hast du irgendwo eine funktion wie 
	
	
	
	





```
int generiereZufallszahl(int min, int max)
```

die kannst du eifach vom test aus entsprechend aufrufen


----------



## KoenigGunther (18. Jul 2007)

Wenn ich aber ne Funktion habe:


```
...palaber bla blubb...

public int funktionZufallsZahl(){
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    String text = in.readLine();
    int min = Integer.parseInt(text);
    int max = Integer.parseInt(in.readLine());

   return min + (Math.random()*(max-min));
}
```

Wie simuliere ich da die Konsoleneingaben - denn die Funktion terminiert ja nicht, wenn nicht 2x von der Konsole gelesen wird.


----------



## Murray (18. Jul 2007)

Eigentlich wäre es besser, die Eingabe von der Berechnung zu trennen (wie von Hoax beschrieben). Dann könnte der Test-Case die "Konsoleneingabe" insofern simulieren, als dass er einfach in einer Schleife immer zwei (zufällige) Werte vorgibt. Wenn es dir aber gerade um den Test der Eingabe geht, könntest du deiner Methode den InputStream als Parameter übergeben. Im Normalbetrieb wird dann System.in übergeben, beim Testen kann der Test-Case dann z.B. einen FileInputStream oder einen ByteArrayInpoutStream mit simulieren Eingaben übergeben.


----------



## KoenigGunther (19. Jul 2007)

Danke für die Antwort!

Wenn ich dann den InputStream mit übergebe läuft es doch eigentlich auch wieder darauf hinaus dass die Funktion die aufgerufen und tetestet wird, Argumente mit übergeben bekommen muss, oder?
Also wäre das praktisch die Lösung von Hoax.

Klar, ich würde das auch so machen. Ich schreibe gerade ein System das Javaaufgaben mit Unit-Tests überprüft. Einige der Aufgaben erfordern halt Konsolen-User-Interaktion und ich hab mich gefragt ob man das mit Unit-Tests realisieren kann.
Ist ja nicht weiter schlimm wenn es nicht geht, schöner natürlich wenn doch  aber so stellt man halt die Aufgabe ein wenig um.

Vielen Dank euch beiden!
Christian


----------



## Murray (19. Jul 2007)

KoenigGunther hat gesagt.:
			
		

> Wenn ich dann den InputStream mit übergebe läuft es doch eigentlich auch wieder darauf hinaus dass die Funktion die aufgerufen und tetestet wird, Argumente mit übergeben bekommen muss, oder?


Ja, die Sigantur der Methode müsste insofern geändert werden, als dass sie jetzt einen InputStream bekommt. Durch Überladen kann man es ja aber schaffen, dass das "normale" API weiterhin erhalten bleibt.

```
public int funktionZufallsZahl(){
   return funktionZufallsZahl( System.in);
}

public int funktionZufallsZahl( InputStream inp){
    BufferedReader in = new BufferedReader(new InputStreamReader( inp));
    String text = in.readLine();
    int min = Integer.parseInt(text);
    int max = Integer.parseInt(in.readLine());

   return min + (Math.random()*(max-min));
}
```



			
				KoenigGunther hat gesagt.:
			
		

> Also wäre das praktisch die Lösung von Hoax.


Nicht ganz. Grundsätzlich würde ich zwar auch dazu raten, die Methode wie von Hoax vorgeschlagen vom Einlesen der Parameter zu entkoppeln und nur die Berechnung für sich zu testen. Wenn du aber a) das API nicht ändern willst und/oder b) eben auch das Einlesen der Parameter testen willst, dann wäre der InputStream eine Lösung dafür, denn damit könntest du z.B. auch die Eingabe von Buchstaben simulieren und feststellen, dass der Code dann auf eine NumberformatException läuft.


----------



## KoenigGunther (19. Jul 2007)

Okay, das werd ich mir nochmal genau überlegen... Im Moment bin ich aber eher in der Stimmung die Aufgaben dahingehend zu ändern als dass man gefälligst eine Funktion mit Parametern schreiben soll 
Danke sehr!


----------

