# Methode testen



## IchMagJava (16. Apr 2020)

Hallo zusammen,

ich soll einen Test für eine Methode schreiben, weiß momentan aber nicht recht wie das gehen soll. Zum Sachverhalt:
Beim Klicken auf eine Schaltfäche wird eine Methode ausgelöst, die im Fenster in einem for-else-Block schaut, ob alle Werte richtig eingetragen sind und bei Abweichungen eine Fehlermeldung ausgibt. Die Methode hat weder Rückgabewert, noch Parameter. Deshalb klappt es auch nicht mit assert-Funktionen. 
Mock-Klassen gehen glaub ich in die richtige Richtung.

Hat einer ne Idee?


----------



## Xyz1 (16. Apr 2020)

Naja dann trag halt Daten/Texte in die Oberfläche ein und überprüfe ob die Methode richtig reagiert.
Nach folgendem Schema: Felder: (1=richtig, 2=falsch)
000
001
010
011
100
usw usf.


----------



## mrBrown (16. Apr 2020)

IchMagJava hat gesagt.:


> Beim Klicken auf eine Schaltfäche wird eine Methode ausgelöst, die im Fenster in einem for-else-Block schaut, ob alle Werte richtig eingetragen sind und bei Abweichungen eine Fehlermeldung ausgibt.


Wie kommt die Methode an die Werte und wie wird die Fehlermeldung ausgegeben?


----------



## Xyz1 (16. Apr 2020)

Ist doch wurscht, sie soll genau diese Methode testen, und das geht über das Eintragen der Werte in das UI.

Und dann noch lässt sich ohne Code und jegliche Beschreibung/Dokumentation so gar nichts dazu sagen.


----------



## mrBrown (16. Apr 2020)

Xyz1 hat gesagt.:


> Ist doch wurscht, sie soll genau diese Methode testen, und das geht über das Eintragen der Werte in das UI.


"Wildes ausprobieren in der GUI" und "Tests schreiben" sind zwei verschiedene Dinge. Irgendwann wird das sicherlich auch bei dir im Unterricht dran kommen


----------



## Xyz1 (16. Apr 2020)

Das nennt sich (functional) System oder Black-Box Testing, ist durchaus gängige Praxis und hier das Mittel der Wahl oder angebracht. Siehe auch: https://www.ranorex.com/resources/testing-wiki/gui-testing/ .

/e Ich sage ja nicht dass diese Tests nicht automatisiert/gescriptet sein sollen... Ich denke für exploratory testings fehlt ihr schlicht die Erfahrung und Grundlagen... Siehe auch: https://en.wikipedia.org/wiki/Exploratory_testing .

/e2 Und zwar habe ich konkret einen Decision table test vorgeschlagen und ihr gezeigt, wie sie die Tabelle dazu aufstellen kann. Wieder ein paar Links:
`https://en.wikipedia.org/wiki/Black-box_testing`
`https://en.wikipedia.org/wiki/Decision_table`

Was stört Dich daran? Sind Dir die Tests zu primitiv - oder findest Du das Programmdesign schlecht?  An Letzterem können wird nüschts ändern.


----------



## M.L. (17. Apr 2020)

> "Wildes ausprobieren in der GUI" und "Tests schreiben"


 Das stimmt zwar, aber auf Testerseite weiss man strenggesehen nie, WAS der Nutzer alles (nicht) tut um ein bestimmtes Resultat (nicht) zu erzielen.
Weiterhin kann man auch Tests aller Art "auf Vorrat" anlegen und kontrollieren, welche scheitern / erfolgreich verlaufen.


----------



## temi (17. Apr 2020)

mrBrown hat gesagt.:


> Wie kommt die Methode an die Werte und wie wird die Fehlermeldung ausgegeben?





Xyz1 hat gesagt.:


> Ist doch wurscht


Finde ich nicht, dass das wurscht ist. Die Frage sollte man sich schon zuerst stellen, bevor man irgendwas anderes macht.


----------



## LimDul (17. Apr 2020)

Man kann sowas auch oft (und da kommen Mocks in Spiel) mit normalen Unit-Tests testen.

Denn auch eine Methode ohne Parameter und Rückgabe macht etwas - den Zustand anderer Objekte ändern. Und das kann man entweder direkt oder indirekt über Mocks testen.


----------



## IchMagJava (17. Apr 2020)

Xyz1 hat gesagt.:


> Siehe auch:


Danke für die Links.


mrBrown hat gesagt.:


> Wie kommt die Methode an die Werte und wie wird die Fehlermeldung ausgegeben?


Beim Klicken auf den OK-Button wird die Methode aufgerufen. Die Methode sieht wie folgt aus:

void Methode()
{
for(SpinBoxA.value() == 0)
show.MesageBox()

else if(SpinBoxB.value() ==0)
show.MessageBox()

...

execute algorithm

}

Die Methode prüft also, ob die Angaben des Benutzers in Spinboxen "korrekt" sind. z.B. dürfen bestimmte Parameter nicht Null sein, sonst springt der Algorithmus nicht an.
Jetzt muss getestet werden, dass die Fehlermeldungen auch erscheinen bei entsprechenden Einträgen.
assertTrue(SpinBoxA.value() == 1, False) irgendwie so...


----------



## LimDul (17. Apr 2020)

Nun,  du willst testen ob eine MessageBox erzeugt wird, wenn bestimmte Einträge da sind.

Jetzt gibt es mehrere Möglichkeiten:

a) (die sauberste): Den Code sauber strukturieren, dass er testbar ist. Das heißt, Logik (Validierung) vom UI (Anzeige der Fehlermeldungen) trennen. Das heißt, du hättest im Modell eine Methode "ValidiereEignabe" die die EIngabe von den SpinBoxen als Parameter bekommt und zurück z.B. eine Liste von Fehlermeldungen gibt. Dann kannst du diese Methode testen, dass sie die korrekte Liste der Fehlermeldungen zurückgibt. 

b)  Versuchen den bestehenden Code zu testen. In dem Fall müsstest versuchen für das Objekt, was die Messagebox erzeugt, einen Mock (z.B.) mit Mockito zu setzen. Dann kannst du prüfen, ob da die Methode MessageBox aufgerufen wurde.


Ich würde aber generell -sofern möglich - zu Möglichkeit a) tendieren. Kann ich einen Code nicht testen, sollte ich so umschreiben, dass ich ihn sinnvoll testen kann.


----------



## Xyz1 (17. Apr 2020)

Ich würde nach wie vor zu einem Black-Box decision table test tendieren, wenn der bestehende Code nicht verändert werden darf/soll/kann.


----------



## IchMagJava (17. Apr 2020)

Xyz1 hat gesagt.:


> Ich würde nach wie vor zu einem Black-Box decision table test tendieren, wenn der bestehende Code nicht verändert werden darf/soll/kann.


Ich kann den code verändern. Insofern habe ich freie Wahl beim Testen.



LimDul hat gesagt.:


> Ich würde aber generell -sofern möglich - zu Möglichkeit a) tendieren. Kann ich einen Code nicht testen, sollte ich so umschreiben, dass ich ihn sinnvoll testen kann.


Dann versuche ich das mal umzusetzen!

Danke an Alle!


----------



## IchMagJava (20. Apr 2020)

Guten Abend,
habe den Code jetzt soweit angepasst, dass die Methode Werte der Spinboxen als Parameter übergeben bekommt und ein Feld aus booleans zurückgibt, wobei jeder boolean für eine Fehlermeldung steht.

Beim Unittest funktioniert erstmal folgender test:

self.assertEqual(okClick([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]), [0, 0, 0, 0, 0]) d.h. Alle Werte auf 1 ergibt keine Fehlermeldung

Dieser Test hingegen schlägt mit dem Fehlercode: -1073740791 (0xC0000409) fehl.

self.assertEqual(okClick([0, 1, 0, 0, 0, 0, 0, 0, 0, 0]), [1, 0, 0, 0, 0]) d.h. die erste Null müsste die erste Fehlermeldung rufen, was im Programm auch 

problemlos klappt, aber im Test fehlschlägt


----------



## mrBrown (20. Apr 2020)

Wenn du wirklich ein boolean-Array zurück gibst würde es mich doch sehr wundern, wenn eine der beides Assertions erfolgreich ist?


----------



## IchMagJava (20. Apr 2020)




----------



## mrBrown (20. Apr 2020)

Was soll das Bild zeigen?


----------



## IchMagJava (20. Apr 2020)

Das Bild zeigt, dass dieser Test: self.assertEqual(okClick([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]), [0, 0, 0, 0, 0]) 
erfolgreich war.


----------



## mrBrown (20. Apr 2020)

Wie angedeutet: dann gibt okClick kein Array von booleans zurück, sondern long/int/short/byte


----------



## IchMagJava (20. Apr 2020)

Nein, es gibt ein Array von 5 booleans zurück,


----------



## mrBrown (20. Apr 2020)

Die Argumente in `self.assertEqual(okClick([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]), [0, 0, 0, 0, 0])` sind dann ein `boolean[]` und ein `int[]`? Wann sind denn das boolean- und das int-Array gleich?


----------



## IchMagJava (20. Apr 2020)

Hier ist mal der Methodenaufbau:

okClick(Array)
bool1
bool2
bool3
bool4
bool5

if (a[0] == 0)
   show.message()
   bool1 = True

else if (a[1] == 0)
    show.message()
    bool2 = True

else if (a[2] == 0 or a[3] == 0 or a[4] == 0)
     show.message()
     bool3 = True

else if (a[5] == 0 or a[6] == 0)
     show.message()
     bool4 = True

else if (((((a[2] - a[7]) + (a[4] - a[9]) + ((a[3] * a[1]) - (a[1] * a[8]))) - (a[5] + a[6])) > a[0]))
     show.message()
     bool5 = True

return [bool1, bool2, bool3, bool4, bool5]


----------



## mrBrown (20. Apr 2020)

Es geht nicht um Java, oder?


----------



## IchMagJava (20. Apr 2020)

Eigentlich Python, sollte aber auf das gleiche hinauslaufen.


----------



## mrBrown (20. Apr 2020)

Und was macht assertEqual?

Auf echte Gleichheit prüfen ja nicht, wenn zwei Arrays mit unterschiedlichen Typen gleich sind?


----------



## IchMagJava (20. Apr 2020)

Habe gerade boolean gegen int eingetauscht, ergo zwei Arrays gleichen Typs werden geprüft, aber gleicher Fehler kommt raus.


----------



## IchMagJava (20. Apr 2020)

Der Fehler scheint ein Stackoverflow zu sein. Aber wie behebe ich ihn?


----------



## mrBrown (20. Apr 2020)

Ich würde mir mehr Sorgen wegen dem Test machen, der trotz unterschiedlicher Typen erfolgreich war...




IchMagJava hat gesagt.:


> Der Fehler scheint ein Stackoverflow zu sein. Aber wie behebe ich ihn?


Naja, die Stelle mit Rekursion suchen und prüfen, warum es nie abbricht.


----------



## IchMagJava (20. Apr 2020)

Okay....habe jetzt die gleichen Tests in einer anderen Entwicklungsumgebung eingegeben und hat fehlerfrei funktioniert


----------



## IchMagJava (20. Apr 2020)

ok doch nicht xD


----------



## IchMagJava (21. Apr 2020)

mrBrown hat gesagt.:


> Naja, die Stelle mit Rekursion suchen und prüfen, warum es nie abbricht.


So komisch es sich auch anhört, hinter dem Fehler steckte das Fehlen einer Application-Klasse bei den Errorboxen.
Danke für die Mühe.


----------

