Automatisches Testen und Bewerten von Java-Klassen Im Rahmen des Seminars „E-Learning“ Christof Wingender c.wingender@uni-muenster.de 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?
Gliederung Einführung Ansätze zum E-Assessment von Java-Klassen 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
Anforderungen an Java-Klassen Korrektheit Robustheit Leichte Wartbarkeit Verständlichkeit Testbarkeit Effiziente Programme (vgl. [PI08])
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)
Gliederung Einführung Ansätze zum E-Assessment von Java-Klassen 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
Praktomat Universität Passau Java, Haskell, C++ Automatische Tests Öffentliche vs. geheime Testfälle DejaGnu Checkstyle Sandbox Peer-Review
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() { } public static void main (String[] args){…} //Declare variables // Print “Please enter integer x: “ // Read x // Print “Please enter integer y: “ // Read y // Print “x / y = “ // Print x / y
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 */
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 </loop> </statements> </gap> <condition> <trueBranch> <falseBranch> <methodCall> Vergleich: Abgabe - Musterlösung
extreme eLearning experience (xLx) Universität Münster Java Automatische Tests Öffentliche vs. geheime Testfälle JUnit Apache Ant Policies
Gegenüberstellung der Ansätze Praktomat ELP xLx Programmierstil Fehlermuster Funktionalität Effizienz
Gliederung Einführung Ansätze zum E-Assessment von Java-Klassen 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
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
Build-Prozess Quelltext
Build-Prozess Quelltext Checkstyle Bericht Programmierstil
Build-Prozess Quelltext Checkstyle FindBugs Bericht Programmierstil Fehlermuster
Build-Prozess Quelltext Testklassen Quelltext javac javac Checkstyle FindBugs .class-Dateien Bericht Programmierstil Bericht Fehlermuster JUnit Bericht Funktionalität
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, ... }
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)); Weiteres Modul: MagicNumber
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);
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;
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))); }
Bewertung Überprüfung Erweiterbar Problematisch Programmierstil Potentielle Fehler Funktionalität Effizienz Erweiterbar Problematisch GUIs, Applets
Gliederung Einführung Ansätze zum E-Assessment von Java-Klassen 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
Fazit Automatische Überprüfung von Keine automatische Überprüfung von Programmierstil Potentiellen Fehlern Funktionalität Keine automatische Überprüfung von Effizienz Aufgaben mit GUI oder Applets Trainingsbereiche Statische Analyse Aufgabenpool
Literaturverzeichnis [AA08] Apache Ant: http://ant.apache.org, Abrufdatum 01.04.2008. [Ch08] Checkstyle: http://checkstyle.sourceforge.net, Abrufdatum 01.04.2008. [ELP08] Environment for Learning to Program: http://elp.fit.qut.edu.au, Abrufdatum 01.04.2008. [FB08] FindBugs: http://findbugs.sourceforge.net, Abrufdatum 01.04.2008. [Ju08] JUnit: http://www.junit.org, Abrufdatum 01.04.2008. [PI08] Praktische Informatik: Informatik I: Kapitel 1: Einführung, http://www.wi.uni-muenster.de/pi/lehre/ws0708/info1/index.php, Abrufdatum 02.04.2008. [PMD08] PMD: http://pmd.sourceforge.net, Abrufdatum 01.04.2008. [Pr08] Praktomat: http//www.fim.uni-passau.de/de/fim/fakultaet/lehrstuehle/softwaresysteme/ forschung/praktomat.html, Abrufdatum 01.04.2008. [Xl08] extreme eLearning experience: http://dbms.uni-muenster.de/xLx, Abrufdatum 02.04.2008.
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();
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)
JUnit Isolierte Ausführung der Testmethoden Keine Seiteneffekte Neue Instanz der Klasse Herstellen der Testumgebung: setUp() Bereinigen der Testumgebung: tearDown()