Unit Tests und Fehlersuche SE 1 - Softwareentwicklungspraktikum Test Deadline! Sinnvolle Tests kompilierbar im CVS d.h. Schnittstellen zu Strategiemethoden etc. schon erstellen Kommentieren! Besser ein Kommentar als keine/unvollständige Testimplementierung! Tests müssen nicht erfolgreich laufen!! Roter Balken (aber müssen startbar sein)! Tests an den Szenarien / Anforderungen orientieren 1 2! Regeln jetzt im Netz Turnier JUnit! Erben von TestCase! public void testxyz() Methoden anlegen! Aufrufe von assertequals( "Beschreibung", SOLL, ist() ); asserttrue( "Beschreibung", ist() ); assertfalse( "Beschreibung", ist ); assertequals( "Beschreibung", SOLL, ist(), delta ); fail(); 3 4
JUnit Einfacher Test! Robot anlegen (eigene Strategie instanzieren)! Methode aufrufen! Ergebnis Kontrollieren public class SimpleStrategyMethodTest extends TestCase { public void testarithmethicmethod() { Corners robot = new Corners(); double result = robot.normalrelativeangle( 182 ); assertequals( "norm angle", -178, result, 0.00001 ); JUnit Komplexerer Test! Battle und einen RobotPeer anlegen! Robot anlegen (eigene Strategie instanzieren)! Peer und Robot verlinken! Strategie auf einen zu testenden Zustand setzen! Methode aufrufen! Ergebnis Kontrollieren evtl. unter Verwendung von Peer und Battle 5 6 JUnit Komplexerer Test public void testadvancedmethod() { Battle battle = new Battle( new DefaultBattleField( 500, 500 ), new RobocodeManager( false, null ) ); RobotClassManager classmanager = new RobotClassManager( new RobotSpecification( new File("irrelevant-string.class"), new File(""), "", false ) { ); battle.addrobot( classmanager ); RobotPeer peer = battle.getrobots().lastelement(); Crazy robot = new Crazy(); peer.setrobot( robot ); robot.setpeer( peer ); JUnit setup und teardown! Jeder TestCase kann einen methode setup haben (public, ohne Parameter)! Wird vor jeder testxy methode aufgerufen! Zusammenfassen von Szenarios mit ähnlicher Anfangssituation peer.setenergy( 100 ); robot.movingforward = true; robot.reversedirection(); assertfalse( "not moving forward any more", robot.movingforward ); assertequals( "distance remaining", -40000, peer.getdistanceremaining(), 1d );! teardown analog nach jedem Test 7 8
setup Beispiel setup Beispiel public void testadvancedmethod() { Battle battle = new Battle( new DefaultBattleField( 500, 500 ), new RobocodeManager( false, null ) ); RobotClassManager classmanager = new RobotClassManager( new RobotSpecification( new File("irrelevant-string.class"), new File(""), "", false ) { ); battle.addrobot( classmanager ); RobotPeer peer = battle.getrobots().lastelement(); Crazy robot = new Crazy(); peer.setrobot( robot ); robot.setpeer( peer ); peer.setenergy( 100 ); robot.movingforward = true; robot.reversedirection(); assertfalse( "not moving forward any more", robot.movingforward ); assertequals( "distance remaining", -40000, peer.getdistanceremaining(), 1d ); public void setup() { Battle battle = new Battle( new DefaultBattleField( 500, 500 ), new RobocodeManager( false, null ) ); RobotClassManager classmanager = new RobotClassManager( new RobotSpecification( new File("irrelevant-string.class"), new File(""), "", false ) { ); battle.addrobot( classmanager ); peer = battle.getrobots().lastelement(); robot = new Crazy(); peer.setrobot( robot ); robot.setpeer( peer ); private RobotPeer peer; private Crazy robot; public void testadvancedmethod() { peer.setenergy( 100 ); robot.movingforward = true; 9 10 JUnit Framework Test JUnit 3 JUnit 4! Hier vorgestellt: JUnit 3 Namenskonventionen zur Markierung der setupund test-methoden, etc.! Siehe Unit test im CVS Repository! JUnit 4 Verwendet Java 5 Annotations zur Markierung Man braucht nicht von TestCase erben 11 12
Debugging! Leif Eclipse Demo 13 14 Debugging Methodische Fehlersuche! zum Einkreisen eines Fehlers! Breakpoints an spannenden Stellen setzen! Variablenbelegung / Objekstruktur überprüfen mit dem Variables View mit edobs! Methode schrittweise ausführen! in interessante Methoden reinsteppen! Vorraussetzungen: Möglichst umfassenden Verständnis des Systems Nicht irgendwas ändern, sondern Arbeitsschritte merken Möglichst zeitnah nach den Änderungen testen 15 16
! Vorgehen Methodische Fehlersuche Nach Änderungen/Neuerungen Tests durchführen (Automatisch oder notfalls manuell) Art des Fehlers feststellen Falls möglich Schlussfolgerungen für Ursachen ziehen Mögliche Ursachen (in Reihenfolge der Wahrscheinlichkeit) überprüfen Falls nicht erfolgreich kleinschrittiger vorgehen!! NullPointerException Fehlerarten Direkte Ursache: Variable/Feld mit null belegt Problematische(s) Feld/Variable über erste Stacktrace- Zeile festzustellen (draufklicken!) Wahrscheinliche mittelbare Ursachen:! Initialisierung von Objekt oder Schleife nicht durchgeführt! Falsche Parameter wurden übergeben! zweite/folgende Stacktrace-Zeile anschauen! Am Anfang/Ende einer Liste/Menge angekommen! Logikfehler? Beseitigung! Recht offensichtlich nach bekannter Ursache 17 18! Andere Exceptions Fehlerarten Grund für die Exception nachschlagen! Teilweise abhängig von der aufgerufenen Methode (im Stacktrace nachgucken) Exception cause nachschauen z.b. wichtig bei InvocationTargetException Erste eigene Codezeile im Stacktrace suchen und überprüfen ob der Aufruf so korrekt sein sollte (evtl. mit Debugger die Parameter überprüfen) Falls Ursache immer noch unbekannt in Methode steppen (Debugger) und nachvollziehen, warum die Exception geworfen wird Stacktrace de.tu_bs.xmlreflect.util.errors.accessorexception: Could not find setter at de.tu_bs.xmlreflect.util.accessormethodsutilizer.setfield(accessormethodsutilizer.java:224) at de.tu_bs.coobra.objectchangeawarehelper.redo(objectchangeawarehelper.java:339) at de.tu_bs.coobra.objectchangeawarehelper.redo(objectchangeawarehelper.java:894) at de.tu_bs.coobra.localrepository.update(localrepository.java:3881) at de.uni_paderborn.fujaba.coobra.actions.checkoutaction.connect(checkoutaction.java:312) at de.uni_paderborn.fujaba.ant.cxrcheckoutgentask.executeimpl(cxrcheckoutgentask.java:120) at de.uni_paderborn.fujaba.ant.abstractgentask.execute(abstractgentask.java:165) at org.apache.tools.ant.unknownelement.execute(unknownelement.java:275) at org.apache.tools.ant.task.perform(task.java:364) at org.apache.tools.ant.target.execute(target.java:341) at org.apache.tools.ant.target.performtasks(target.java:369) at org.apache.tools.ant.project.executesortedtargets(project.java:1216) Caused by: java.lang.nosuchmethodexception: settarget( String ) at de.tu_bs.xmlreflect.util.accessormethodsutilizer.setfield(accessormethodsutilizer.java:234)... 19 more 19 20
Fehlerarten! Unerwartete Ergebnisse Ursache eingrenzen z.b. durch divide and conquer An problematischer Stelle steppen und einzelne Eingabe- und Ausgabewerte überprüfen und Operationen nachvollziehen Fazit! Test zum Fehler Bemerken! Im Fehlerfall Fehler eingrenzen Debugging! Immer: Kopf benutzen! 21 22