Wirtschaftsinformatik Automatisches Testen und Bewerten von Java-Klassen Im Rahmen des Seminars „E-Learning“ Christof Wingender [email protected] 15./16. Mai 2008 Motivation ■ Papierbasierte Lernfortschrittskontrolle ■ Klausur, Übungen ■ Medienbrüche ■ Personal- und Zeitaufwändig ■ Menschliche Fehler, Subjektivität ■ Lösung: E-Assessment von Java-Klassen? 2 Gliederung ■ Einführung ■ Anforderungen an Java-Klassen ■ Analyse von Java-Klassen ■ Ansätze zum E-Assessment von Java-Klassen ■ Praktomat ■ Environment for Learning to Program ■ extreme eLearning experience ■ Erweiterung der Ansätze ■ Fazit 3 Anforderungen an Java-Klassen ■ ■ ■ ■ ■ ■ Korrektheit Robustheit Leichte Wartbarkeit Verständlichkeit Testbarkeit Effiziente Programme (vgl. [PI08]) 4 Analyse von Java-Klassen ■ Statische Analyse ■ Keine Ausführung des Programms ■ Syntax, Semantik ■ Programmierstil ■ Fehlermuster im Quelltext ■ Dynamische Analyse ■ Ausführung des Programms ■ Unit-Test (Komponententest) 5 Gliederung ■ Einführung ■ Anforderungen an Java-Klassen ■ Analyse von Java-Klassen ■ Ansätze zum E-Assessment von Java-Klassen ■ Praktomat ■ Environment for Learning to Program ■ extreme eLearning experience ■ Erweiterung der Ansätze ■ Fazit 6 Praktomat ■ Universität Passau ■ Java, Haskell, C++ ■ Automatische Tests ■ Öffentliche vs. geheime Testfälle ■ DejaGnu ■ Checkstyle ■ Sandbox ■ Peer-Review 7 Environment for Learning to Program (ELP) ■ Queensland Universität in Brisbane ■ C#, C++, Java, Pascal, Visual Basic ■ Beispielaufgabe: IntegerDivision: import TerminalIO.*; public class IntegerDivision { KeyboardReader reader = new KeyboardReader(); ScreenWriter writer = new ScreenWriter(); public void run() { //Declare variables // Print “Please enter integer x: “ // Read x // Print “Please enter integer y: “ // Read y // Print “x / y = “ // Print x / y } public static void main (String[] args){…} } 8 Environment for Learning to Program (ELP) ■ Programmierstil-Überprüfung: Java-Reflection API ■ Normalisierung Quelltext-Fragment /* Zu lösender Abschnitt: */ vor = 0; nach = 1; for (int i = 3; i<= grenze; i++){ hilf = vor + nach vor = nach; nach = hilf } /* Ende zu lösender Abschnitt */ 9 Environment for Learning to Program (ELP) ■ Programmierstil-Überprüfung: Java-Reflection API ■ Normalisierung Quelltext-Fragment Normalisierte Form /* Zu lösender Abschnitt: */ vor = 0; nach = 1; for (int i = 3; i<= grenze; i++){ hilf = vor + nach vor = nach; nach = hilf } /* Ende zu lösender Abschnitt */ <gap> <statements> <assignment>2 </assignment> <loop> <assignment>3 </assignment> </loop> </statements> </gap> ■ Vergleich: Abgabe - Musterlösung 10 extreme eLearning experience (xLx) ■ Universität Münster ■ Java ■ Automatische Tests ■ Öffentliche vs. geheime Testfälle ■ JUnit ■ Apache Ant ■ Policies 11 Gegenüberstellung der Ansätze Praktomat ELP xLx Programmierstil Fehlermuster Funktionalität Effizienz 12 Gliederung ■ Einführung ■ Anforderungen an Java-Klassen ■ Analyse von Java-Klassen ■ Ansätze zum E-Assessment von Java-Klassen ■ Praktomat ■ Enviroment for Learning to Program ■ extreme eLearning experience ■ Erweiterung der Ansätze ■ Fazit 13 Erweiterung ■ Apache Ant Buildfile ■ Buildfile enthält Projekt und beschreibt, wie ■ Anwendung zu erstellen, ■ zu testen und ■ zu deployen ist <?xml version=“1.0“ ?> <project name=“myProject“ default=“makedir“> <target name=“makedir“> <mkdir dir=“build/classes“ /> <mkdir dir=“test/reports“ /> </target> </project> Project Target Task 14 Build-Prozess Quelltext 15 Build-Prozess Quelltext Checkstyle Bericht Programmierstil 16 Build-Prozess Quelltext Checkstyle Bericht Programmierstil FindBugs Bericht Fehlermuster 17 Build-Prozess Quelltext Testklassen javac Quelltext javac .class-Dateien Checkstyle Bericht Programmierstil FindBugs Bericht Fehlermuster JUnit Bericht Funktionalität 18 Beispiel: Fahrrad.class public class Fahrrad { private Rahmen rahmen; private boolean einrad; private String marke; public boolean isEinrad() { if (einrad == true) { return true; } else { return false; } } public boolean isEqualRahmen(Rahmen rahmen) { return ( (this.rahmen != null) & this.rahmen.equals(rahmen) ); } } public boolean isEqualMarke(String marke) { return (this.marke == marke); } //Getter, Setter, ... 19 Checkstyle ■ Statische Analyse ■ Überprüft Programmierstil ■ JavaDoc ■ Namenskonventionen ■ … ■ Konfiguration über XML-Datei ■ Beispiel: String-Vergleiche (==, != statt equals) <module name="StringLiteralEquality"/> public boolean isEqualMarke(String marke) { return (this.marke == marke);} Richtig: return ((this.marke.equals(marke)); 20 FindBugs ■ Statische Analyse ■ Findet mögliche Fehler ■ Beispiel: Nullpointer public boolean isEqualRahmen(Rahmen rahmen) { return((this.rahmen != null) & this.rahmen.equals(rahmen));} Besser: return ((this.rahmen != null) && this.rahmen.equals(rahmen); 21 Alternative: PMD ■ Statische Analyse ■ Wie FindBugs ■ Zusätzlich: ■ Suboptimaler Quelltext ■ Unbenutzer Quelltext ■ Beispiel: Vergleiche in booleschen Ausdrücken public boolean isEinrad() { if(einrad == true) { return true; } else { return false; }} Besser: return einrad; 22 JUnit ■ ■ ■ ■ Dynamische Analyse Komponententest Stichprobenverfahren Beispiel: isEqualRahmen public void testIsEqualRahmen() { Fahrrad rad = new Fahrrad(); rad.setEinrad (false); rad.setRahmen (new Rahmen("rot", 48)); assertEquals (true, rad.isEqualRahmen(new Rahmen ("rot", 48))); } 23 Bewertung ■ Überprüfung ■ Programmierstil ■ Potentielle Fehler ■ Funktionalität ■ Effizienz ■ Erweiterbar ■ Problematisch ■ GUIs, Applets 24 Gliederung ■ Einführung ■ Anforderungen an Java-Klassen ■ Analyse von Java-Klassen ■ Ansätze zum E-Assessment von Java-Klassen ■ Praktomat ■ Enviroment for Learning to Program ■ extreme eLearning experience ■ Erweiterung der Ansätze ■ Fazit 25 Fazit ■ Automatische Überprüfung von ■ Programmierstil ■ Potentiellen Fehlern ■ Funktionalität ■ Keine automatische Überprüfung von ■ Effizienz ■ Aufgaben mit GUI oder Applets ■ Trainingsbereiche ■ Statische Analyse ■ Aufgabenpool 26 Literaturverzeichnis [AA08] [Ch08] [ELP08] [FB08] [Ju08] [PI08] [PMD08] [Pr08] [Xl08] Apache Ant: http://ant.apache.org, Abrufdatum 01.04.2008. Checkstyle: http://checkstyle.sourceforge.net, Abrufdatum 01.04.2008. Environment for Learning to Program: http://elp.fit.qut.edu.au, Abrufdatum 01.04.2008. FindBugs: http://findbugs.sourceforge.net, Abrufdatum 01.04.2008. JUnit: http://www.junit.org, Abrufdatum 01.04.2008. Praktische Informatik: Informatik I: Kapitel 1: Einführung, http://www.wi.uni-muenster.de/pi/lehre/ws0708/info1/index.php, Abrufdatum 02.04.2008. PMD: http://pmd.sourceforge.net, Abrufdatum 01.04.2008. Praktomat: http//www.fim.uni-passau.de/de/fim/fakultaet/lehrstuehle/softwaresysteme/ forschung/praktomat.html, Abrufdatum 01.04.2008. extreme eLearning experience: http://dbms.uni-muenster.de/xLx, Abrufdatum 02.04.2008. 27 Java-Reflection API ■ Zur Laufzeit Informationen zur Struktur einer Klasse // Klasse „laden“ Class<?> fahrrad = Class.forName("Fahrrad"); // Attribute der Klasse Fahrrad Field fields[] = fahrrad.getDeclaredFields(); // Methoden der Klasse Fahrrad Method methods[] = fahrrad.getDeclaredMethods(); 28 Sicherheitsmanager ■ Zwischen Aufrufer und Betriebssystem ■ Kontrolle über problematische (gefährliche) Methoden der Java-Bibliothek ■ Rechtevergabe: Policy-Datei ■ grant-Anweisungen grant { permission java.io.FilePermission “<Filename>“, “read“;}; ■ Nachteile ■ Keine Rollen ■ Kein Refresh (Neustart der Applikation) 29 JUnit ■ ■ ■ ■ Isolierte Ausführung der Testmethoden Keine Seiteneffekte Neue Instanz der Klasse Herstellen der Testumgebung: setUp() Bereinigen der Testumgebung: tearDown() Assert Test TestCase TestSuite 30