<?xml version="1.0" encoding="UTF-8"?>
<TEI xml:space="preserve" xmlns="http://www.tei-c.org/ns/1.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.tei-c.org/ns/1.0 https://raw.githubusercontent.com/kermitt2/grobid/master/grobid-home/schemas/xsd/Grobid.xsd"
 xmlns:xlink="http://www.w3.org/1999/xlink">
	<teiHeader xml:lang="de">
		<fileDesc>
			<titleStmt>
				<title level="a" type="main">Sicherheitsimplikationen beim Einsatz von Test Doubles zur automatisierten Bewertung studentischer Java-Programme mit Graja und mockito</title>
			</titleStmt>
			<publicationStmt>
				<publisher/>
				<availability status="unknown"><licence/></availability>
			</publicationStmt>
			<sourceDesc>
				<biblStruct>
					<analytic>
						<author role="corresp">
							<persName><forename type="first">Robert</forename><surname>Garmann</surname></persName>
							<email>robert.garmann@hs-hannover.de</email>
							<affiliation key="aff0">
								<orgName type="department">Fakultät IV -Wirtschaft und Informatik Ricklinger Stadtweg</orgName>
								<orgName type="institution">Hochschule Hannover</orgName>
								<address>
									<postCode>120, 30459</postCode>
									<settlement>Hannover</settlement>
								</address>
							</affiliation>
						</author>
						<title level="a" type="main">Sicherheitsimplikationen beim Einsatz von Test Doubles zur automatisierten Bewertung studentischer Java-Programme mit Graja und mockito</title>
					</analytic>
					<monogr>
						<imprint>
							<date/>
						</imprint>
					</monogr>
					<idno type="MD5">D3CD07E7F80A72E132B709E436FED94A</idno>
				</biblStruct>
			</sourceDesc>
		</fileDesc>
		<encodingDesc>
			<appInfo>
				<application version="0.7.2" ident="GROBID" when="2023-03-24T22:10+0000">
					<desc>GROBID - A machine learning software for extracting information from scholarly documents</desc>
					<ref target="https://github.com/kermitt2/grobid"/>
				</application>
			</appInfo>
		</encodingDesc>
		<profileDesc>
			<abstract>
<div xmlns="http://www.tei-c.org/ns/1.0"><p>Wir demonstrieren, dass der Einsatz von Test Doubles bei der automatisierten Bewertung studentischer Java-Programme besondere Sicherheitsfragen aufwirft. Wie skizzieren kurz eine mögliche Antwort auf diese Fragen.</p><p>Im ersten Teil demonstrieren wir die Erstellung eines sog. AssignmentGraders, der in der Lage ist, interne Programmschnittstellen eines maschinell zu bewertenden Java-Programms zu beobachten. Beispielhaft nutzen wir den Autobewerter Graja in Verbindung mit mockito Test Doubles. Wir zeigen, wie man Leistungsaspekte einer studentischen Lösung einzeln und gezielt automatisiert bewertet. Bei einer Beschränkung auf die Beobachtung externer Programmschnittstellen würden sich diese Aspekte der gezielten Bewertung entziehen. Im zweiten Teil beleuchten wir Bedrohungen des das zu bewertende Programm ausführenden Systems und gewichten ausgewählte Ursachen. Wir konzentrieren uns auf Bedrohungen, die mit Mitteln der Java-2-Sicherheitsarchitektur beherrschbar sind und liefern einige Beispiele zur Abgrenzung. Die Eigenheiten der Java-2-Sicherheitsarchitektur werfen im Kontext des Test Double Einsatzes Fragen auf, die wir im dritten Teil erörtern. Test Doubles sollten in einem anderen Schutzbereich der Java-2-Sicherheitsarchitektur als der studentische Code liegen. Um eine privilegierte Ausführung der Test Doubles auch dann zu forcieren, wenn der Aufruf aus studentischem Code erfolgt, schlagen wir den Einsatz von Proxy-Objekten vor. Um auch Nicht-Spezialisten der beschriebenen Sicherheitsbelange die Autorenschaft von AssignmentGradern zu ermöglichen, entwickeln wir eine Wrapper-Bibliothek für mockito, deren zentrale Entwurfsideen wir kurz skizzieren.</p></div>
			</abstract>
		</profileDesc>
	</teiHeader>
	<text xml:lang="de">
		<body>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="1.">Einleitung</head><p>Automatisierte Bewertung studentischer Programme wird in der Informatik-Lehre zurzeit überwiegend im formativen Assessment eingesetzt. Zeit-und ortsunabhängiges, maschinell erstelltes, quantitatives und qualitatives Feedback soll Studierende in die Lage versetzen, ihre (Teil-)lösungen zu Programmierübungen schrittweise zu verbessern.</p><p>Studentische Programme müssen funktionale und nichtfunktionale Anforderungen erfüllen, die mit statischen oder dynamischen Analyseverfahren untersucht werden können. Für die Analyse der "inneren Qualität" des Bewertungsobjekts spielt die dynamische Analyse an internen Programmschnittstellen (Methodenaufruf) eine wichtige Rolle. Unittest-Frameworks wie JUnit wurden dazu entwickelt, kleinste Einheiten eines Testobjekts durch Methodenaufruf und Verifizierung des Ergebnisses dynamisch zu untersuchen. Um die zu untersuchende Einheit für die Dauer des Tests vom Restsystem zu isolieren werden Test Doubles einge-setzt, die z. B. mittels der Bibliothek mockito <ref type="bibr" target="#b3">[Ka13]</ref> erstellt werden. An einer Beispielaufgabe verdeutlichen wir in Abschnitt 2, wie der JUnit-basierte Autobewerter Graja und mockito zur Beobachtung interner Programmschnittstellen genutzt werden können.</p><p>Das studentische Programm wird bei der dynamischen Analyse ausgeführt. Sicherheitsmaßnahmen auf dem Bewertungsrechner sind notwendig, um ungewolltes oder böswilliges Fehlverhalten des studentischen Programms zu unterbinden. In Abschnitt 3 stellen wir das betrachtete Modell eines Bewertungssystems vor und diskutieren relevante Sicherheitsaspekte.</p><p>Bibliotheken wie mockito wurden nicht für die automatisierte Programmbewertung entworfen. Die Sicherheit der Testumgebung spielt beim (Regressions-)Test großer Softwaresysteme meist eine untergeordnete Rolle. Im Bewertungsszenario jedoch wirft der Einsatz einer solchen Bibliothek essentielle Sicherheitsfragen auf, für die wir in Abschnitt 4 eine mögliche Lösung vorstellen.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="2.">Beobachtung programminterner Schnittstellen</head><p>Die Frage, wann ein studentisches Programm gut ist, ist nicht leicht zu beantworten. Neben dem Kriterium der funktionalen Korrektheit muss das Programm nichtfunktionale Kriterien erfüllen (Effizienz, Änderbarkeit, …). Einige dieser Kriterien lassen sich recht gut automatisiert untersuchen. Grundsätzlich gibt es zwei Herangehensweisen bei der maschinellen Untersuchung eines Bewertungsobjektes <ref type="bibr" target="#b8">[SL05]</ref>: die statische Code-Analyse (bspw. in <ref type="bibr" target="#b7">[SBG10]</ref>) und die dynamische Code-Analyse (bspw. in <ref type="bibr" target="#b4">[KSZ02]</ref>, <ref type="bibr" target="#b1">[Ed03]</ref>). In diesem Aufsatz befassen wir uns mit der letztgenannten Herangehensweise, der Beobachtung des Verhaltens eines studentischen Java-Programms durch Tests.     </p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="2.1">Graja</head></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="2.2">Beispielaufgabe</head></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3.3">Bedrohungspotential</head></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3.4">Bedrohungen im Einflussbereich des Java Securitymanagers</head><p>Uns interessieren ganz allgemein alle Bedrohungen der Vertraulichkeit und Integrität der Daten auf dem die JVM beherbergenden System (Dateien, Nutzerdaten, Musterlösungen, …), sowie alle Bedrohungen der Verfügbarkeit des Bewertungsdienstes. Wir wollen mit der Bedrohungsanalyse dieses Kapitels keine konkret auszumerzenden Schwachstellen identifizieren, sondern es soll hier darum gehen, einige mögliche Angriffe mit ihren Auswirkungen ("impacts") zu benennen, die genügend Motivation liefern, um den Einsatz des Java Securitymanagers für sinnvoll zu erachten. In der folgenden Darstellung nehmen wir die zu motivierende Maßnahme vorweg: den Einsatz des Securitymanagers. Die Motivation der Maßnahme durch Angriffsbeispiele folgt in Abschnitt 3.4.2. </p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3.4.1">Einsatz der Java Sicherheitsarchitektur</head></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3.4.2.1">"rm -rf /"</head><p>Ein bösartiges Beispiel für Submission-Code, welcher versucht, alle Dateien im Dateisystem zu löschen:</p><p>Runtime.getRuntime().exec("rm -rf /");</p><p>Durch Gewährung selektiver Dateizugriffsrechte mittels der Java Sicherheitsarchitektur oder auch mittels der vom Betriebssystem verwalteten Dateirechte kann dieser Angriff gut abgewehrt werden.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3.4.2.2">Denial of service</head><p>Ein anderes Beispiel, das versucht Schaden anzurichten, in dem es die Festplatte füllt 10 :</p><p>FileOutputStream f=new FileOutputStream("x"); while (true) f.write(42); </p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3.4.2.3">"/etc/passwd"</head><p>Es folgt ein Beispiel, das versucht, die Liste der Benutzernamen des Systems auszuspähen:</p><p>System.out.println(Files.readAllLines(new File("/etc/passwd"). toPath(), Charset.forName("UTF-8")));</p><p>Da die Datei /etc/passwd i. d. R. für jeden Systemnutzer lesbar ist, können vom Betriebssystem verwaltete Dateirechte nicht greifen. Dies ist eine Bedrohung, die durch selektive Rechte gemäß der Java Sicherheitsarchitektur abwehrbar ist.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3.4.2.4">Ausspähen der Musterlösung</head><p>Ist etwa der Klassenname einer Musterlösung, die häufig Teil der AssignmentGrader-Komponente ist, bekannt oder erraten worden, könnte man wie folgt versuchen, an den Bytecode der Musterlösung zu kommen:</p><p>InputStream is= Class.forName("org.domain.sample.Solution"). getResourceAsStream("Solution.class"); int b; while ((b= is.read()) &gt;= 0) System.out.print(b+" ");</p><p>Die Standardausgabe wird dem Autor der Submission i. d. R. zur Erläuterung der Bewertung angezeigt.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head>Dieser</head><p>Angriff ist leicht mit Mitteln der Java Sicherheitsarchitektur abwehrbar, indem das Recht zum Einlesen des AssignmentGrader-jar-Archivs nicht gewährt wird.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3.4.2.5">Ausführen der Musterlösung</head><p>Die Submission könnte versuchen, die Musterlösung einfach auszuführen und dadurch die generierten Ausgaben als die eigenen zu "verkaufen". Dieser Angriff lässt sich abwehren, indem die Musterlösungsklasse als package private deklariert wird und indem Submission-Code das Recht zur Überwindung der Package-Kapselung nicht erhält. 10 Bei diesem Beispiel kann es sich auch um eine unabsichtlich herbeigeführte Bedrohung handeln.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.1">Wirkung der Schutzbereiche zur Laufzeit</head><p>Die drei in Abschnitt 3.1 eingeführten Schutzbereiche werden üblicherweise der Klasse der Anwendungsbereiche (application domains) zugeordnet. Ein vierter Schutzbereich mit i. d. R. uneingeschränkten Rechten ist der Systembereich (system domain), dem u. a. die Klassen der Java-Standardbibliothek angehören.</p><p>Bei eingeschaltetem Securitymanager prüft die JVM zur Laufzeit alle an der aktuell aufzurufenden Operation beteiligten Komponenten auf dem Aufrufstapel.   Entwurfsidee 3: Für weitere Klassen der mockito-Bibliothek werden nun (einfachere) Wrapper geschrieben werden. Bspw. besitzt OngoingStubbingWrap&lt;T&gt; ein Instanzattribut vom Originaltyp OngoingStubbing&lt;T&gt;. Methodenaufrufe wie thenReturn werden an das Instanzattribut delegiert. Rückgabewerte werden wieder in Objekte der …Wrap-Klasse eingehüllt. </p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.3">Zentrale Entwurfsideen von Mockito-Wrap</head></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="5.">Fazit</head></div><figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_0"><head></head><label></label><figDesc>Abbildung 5: Drei geladene Komponenten3.2 Benötigte RechteDer AutograderCore benötigt für seine Funktion weitgehende Rechte (Zugriffe auf das lokale Dateisystem, Ausführen des Compilers, Verwendung eigener Klassenlader, Zugriff auf Reflection-Funktionen, etc.). Die Submission benötigt in der Regel wenige Rechte, wobei dies sicher von der Art der zu lösenden Programmieraufgabe abhängt. Dazwischen im Sinne der Rechtemenge steht der AssignmentGrader, der häufig grundlegende Rechte für Dateizugriffe, manchmal auch weitergehende Rechte besitzen muss. Eine Teilmengenbeziehung zwischen den benötigten Rechtemengen der drei genannten Schutzbereiche besteht nicht notwendigerweise.</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_1"><head></head><label></label><figDesc>von AssignmentGradern wird die Sicherheit des Autobewerters so wichtig sein, dass sie die Mühe auf sich nehmen und eine Klasse Proxy&lt;T&gt; für jeden zu doublenden Typ T programmieren wollen. Es handelt sich zudem um höchst spezialisierten Code, der ein tiefes Verständnis von Java Reflection und Generics erfordert.Die naheliegende Idee ist nun, die Erzeugung der Proxy-Objekte in eine Bibliothek auszulagern, die dem AssignmentGrader-Schutzbereich angehört. Wir stellen im folgenden Abschnitt kurz die Entwurfsideen einer neuen Bibliothek MockitoWrap als Hülle um mockito vor, die sich um die Erzeugung von Proxy-Objekten kümmert, welche Aufrufe an Test Doubles delegiert, wobei jeder delegierte Aufruf in ein doPrivileged-Konstrukt "verpackt" ist.</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_2"><head></head><label></label><figDesc>Wählt man wie in Graja JUnit-Tests als Werkzeug zur automatisierten Programmbewertung, ist der Einsatz einer Bibliothek zur Erzeugung von Test Doubles naheliegend. Studentischer Code und Test Doubles gehören verschiedenen Schutzbereichen an. Test Doubles sind im Aufrufbaum Kinder des studentischen Codes, so dass tendenziell restriktive Rechte des studentischen Codes an Test Doubles vererbt werden. Mock-Bibliotheken benötigen für ihre Test Doubles jedoch Rechte von erheblichem Bedrohungspotential. Um den von der Lehrkraft geschriebenen Bewertungscode nicht mit sicherheitsspezifischen Details (Proxy-Objekte mit in doPrivileged-Aufrufen gekapselten Delegationen) zu "verschmutzen", bietet sich die Verlagerung dieser Details in die Mock-Bibliothek oder in einen hierfür zu schreibenden Adapter an. Die Erstellung eines solchen Adapters kann durch Nutzung von Java Generics und der Java-Reflection-Bibliothek kompakt gelingen.</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_0"><head></head><label></label><figDesc>Benutzer des studentischen Programms bedient werden können. Um ein Bewertungsobjekt nun automatisiert mit Eingaben über die genannten Schnittstellen zu versorgen und die Ausgaben maschinell auszuwerten, werden Autobewerter wie der hier eingesetzte Graja<ref type="bibr" target="#b9">[St13]</ref> verwendet. Ein automatisiertes Bewertungsverfahren nimmt bei Nutzung der oben genannten Schnittstellen das Bewertungsobjekt als "black box" wahr und kann wenig über die Qualität der inneren Struktur des Bewertungsobjekts erfahren. Gut überprüfbar ist die funktionale Korrektheit und die Überprüfung einiger nichtfunktionaler Eigenschaften (z. B. Ressourcenverbrauch). Um mehr über die "innere Qualität" des Bewertungsobjekts zu erfahren, ist es hilfreich, das studentische Programm an internen Programmschnittstellen zu beobachten. Eine geeignete Schnittstelle ist der Methodenaufruf mit Methodenparametern als Eingabe und Methodenrückgabe als Ausgabe. Im Folgenden geben wir einen kurzen Überblick über die Funktionen von Graja und stellen eine Beispielaufgabe vor. Danach zeigen wir, wie studentische Lösungsversuche für diese Aufgabe mit Graja unter Einsatz von Test Doubles bewertet werden können.</figDesc><table><row><cell>Bei der dynamischen Code-Analyse beobachtet man das</cell></row><row><cell>Laufzeitverhalten des Bewertungsobjekts an beobachtbaren</cell></row><row><cell>Schnittstellen. Hervorragend geeignet für die Überprüfung der</cell></row><row><cell>funktionalen Korrektheit des Bewertungsobjekts sind Ein-und</cell></row><row><cell>Ausgabeschnittstellen des Benutzers, die auch leicht einer</cell></row><row><cell>maschinellen Bedienung bzw. Abfrage zugänglich sind.</cell></row><row><cell>Interessante Schnittstellen für die Bewertung des studentischen</cell></row><row><cell>Programmverhaltens sind u. a. 1 Tastatureingabe, Consolenaus-</cell></row><row><cell>gabe, Mauseingabe, GUI-Ausgabe [TE08], Kommandozeilen-</cell></row><row><cell>argumente beim Programmstart, Dateiein-/-ausgabe. Allen</cell></row><row><cell>genannten Schnittstellen gemein ist, dass sie prinzipiell auch vom</cell></row></table></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_1"><head></head><label></label><figDesc>Graja ("Grading Java programs") ist i. w. ein Überbau über dem JUnit 2 -Testframework und hat seine Charakterzüge von seinem Vorbild WebCAT<ref type="bibr" target="#b1">[Ed03]</ref> geerbt. Graja bietet u. a. folgende Funktionen:</figDesc><table><row><cell cols="6"> Extrahieren und Übersetzen von Code aus einem ZIP-Archiv,</cell></row><row><cell cols="6"> Umleitung von Standard-Ein/Ausgabeströmen zur Verein-</cell></row><row><cell cols="6">fachung der maschinellen Steuerung des Bewertungsobjekts,</cell></row><row><cell cols="6"> intelligente Vergleiche von erwarteter und beobachteter Aus-</cell></row><row><cell cols="3">gabe eines Bewertungsobjekts,</cell><cell></cell><cell></cell><cell></cell></row><row><cell cols="6"> bequeme "reflection"-basierte Analyse studentischen Codes,</cell></row><row><cell cols="6"> Generierung formatierter, zielgruppenorientierter, und nach</cell></row><row><cell cols="4">Kritikalität abgestufter Bewertungskommentare,</cell><cell></cell><cell></cell></row><row><cell cols="6"> abgestufte Punktevergabe für verschiedene vom Dozenten</cell></row><row><cell cols="3">festzulegende Bewertungsaspekte,</cell><cell></cell><cell></cell><cell></cell></row><row><cell cols="6"> Übersetzung und Ausführung von "on the fly" generiertem</cell></row><row><cell cols="3">Java-Code während der Bewertung,</cell><cell></cell><cell></cell><cell></cell></row><row><cell cols="6"> Begrenzung der genutzten Systemresourcen (Laufzeit,</cell></row><row><cell cols="4">persistenter Speicherplatz, Hauptspeicher),</cell><cell></cell><cell></cell></row><row><cell> Ausführung</cell><cell>des</cell><cell>studentischen</cell><cell>Codes</cell><cell>und</cell><cell>des</cell></row><row><cell cols="6">Bewertungscodes in verschiedenen, separat abgesicherten</cell></row><row><cell cols="2">Schutzbereichen.</cell><cell></cell><cell></cell><cell></cell><cell></cell></row></table></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_2"><head>Abbildung 1: Stark vereinfachte Beispielaufgabe 2.3 Bewertung mit Graja</head><label></label><figDesc></figDesc><table><row><cell>Den Bewertungsaspekt (1) überprüft der in Abbildung 2 dar-</cell></row><row><cell>gestellte, mit Graja kompatible Code.</cell></row><row><cell>Der Aufruf der internen Programmschnittstelle des studentischen</cell></row><row><cell>Codes ist in Programmzeile 06 zu finden. Davor wird eine Instanz</cell></row><row><cell>der studentischen Klasse erzeugt und danach das beobachtete</cell></row><row><cell>Ergebnis überprüft. Diese Art von Bewertungscode ist dem in der</cell></row><row><cell>professionellen Softwareentwicklung verbreiteten Testcode für</cell></row><row><cell>Modultests sehr ähnlich. Spezialitäten der hier betrachteten</cell></row><row><cell>Programmbewertung sind die in Zeile 01 vergebenen Teilpunkte</cell></row><row><cell>und der in Zeile 08f zu findende ausführliche Fehlerhinweis.</cell></row><row><cell>Weiterhin besonders ist die von Graja angebotenen Reflection-</cell></row><row><cell>Bibliothek (Zeile 04f), die etwaige Exceptions in verständliche</cell></row><row><cell>Fehlermeldungen verwandelt.</cell></row><row><cell>Wir betrachten eine für Zwecke der konzentrierten Darstellung</cell></row><row><cell>stark vereinfachte Programmieraufgabe (s. Abbildung 1).</cell></row><row><cell>Diese Aufgabe verlangt vom Studierenden nicht nur die</cell></row><row><cell>Programmierung einer einfachen mathematischen Formel,</cell></row><row><cell>sondern die Implementierung einer vorgegebenen Schnittstelle.</cell></row><row><cell>Eine korrekte Lösung kann nicht nur Hypotenusen berechnen (2);</cell></row><row><cell>eine korrekte Lösung kann darüber hinaus Quadrate berechnen (1)</cell></row><row><cell>und sie setzt Wiederverwendung durch Delegation ein (3). Für</cell></row><row><cell>jeden der im vorstehenden Satz markierten Bewertungsaspekte</cell></row><row><cell>möchten wir Teilpunkte vergeben.</cell></row><row><cell>2 http://junit.org/</cell></row></table></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_3"><head>Abbildung 2: Bewertung des Aspekts (1) Abbildung 3: Bewertung des Aspekts (2) Abbildung 4: Bewertung des Aspekts (3)</head><label></label><figDesc>Berechnen Sie die Länge der Hypotenuse eines rechtwinkligen Dreiecks. Teilen Sie den Programmcode auf zwei Klassen auf: Schreiben Sie eine weitere Klasse Hypo mit einer statischen Methode hypo, die als ersten Parameter ein Quadrat-Objekt und als zwei weitere Parameter die Längen zweier Katheten erhält. Gewünschter Rückgabewert ist die Länge der Hypotenuse. Quadrierungen soll hypo an das Quadrat-Objekt delegieren. Der Code in Abbildung 3 verwendet in Zeile 14 die Bibliothek mockito 3 zur Erzeugung eines Stubs, welches das Interface Quadrat vollständig implementiert. Die beiden folgenden Zeilen "bestücken" das Stub mit vorbereiteten Antworten auf erwartete Anfragen des SUT 4 . In Zeile 17f kommt das SUT (hier die studentische Methode hypo) zur Ausführung. Als Übergabeparameter erhält hypo das Stub-Objekt.</figDesc><table><row><cell cols="2">QuadratImpl</cell><cell>implementiere das folgende vorgegebene</cell></row><row><cell cols="2">Interface:</cell></row><row><cell cols="3">package de.hsh.prog;</cell></row><row><cell cols="3">public interface Quadrat {</cell></row><row><cell></cell><cell cols="2">double quadrat(double v); // berechnet v²</cell></row><row><cell>}</cell><cell></cell></row><row><cell cols="3">01 @Test @ScoringWeight(35.0)</cell></row><row><cell cols="3">02 public void pruefeQuadratMethode() {</cell></row><row><cell>03</cell><cell cols="2">double a= 3, expected= a*a;</cell></row><row><cell>04</cell><cell cols="2">Quadrat studentImpl= ReflectionSupport.create(</cell></row><row><cell>05</cell><cell cols="2">getSubclassForName("QuadratImpl",Quadrat.class));</cell></row><row><cell>06</cell><cell cols="2">double observed= studentImpl.quadrat(a);</cell></row><row><cell>07</cell><cell cols="2">org.junit.Assert.assertEquals(</cell></row><row><cell>08</cell><cell cols="2">"quadrat("+a+")="+observed+" (erwartet :"+expected</cell></row><row><cell>09</cell><cell cols="2">+")", expected, observed, 1E-5);</cell></row><row><cell>10 }</cell><cell></cell></row><row><cell cols="3">11 @Test @ScoringWeight(25.0)</cell></row><row><cell cols="3">12 public void pruefeGesamtfunktion() {</cell></row><row><cell>13</cell><cell cols="2">double a=3, b=4, cExpected=5;</cell></row><row><cell cols="3">14 21 } 22 @Test @ScoringWeight(40.0) Quadrat stub= Mockito.5); 23 public void pruefeAufrufVonQuadrat() { 24 double a=3, b=4; 25 Quadrat mock= Mockito.mock(Quadrat.class); 26 ReflectionSupport.invokeStatic( 27 getClassForName("Hypo"),double.class,"hypo",mock,a,b); 28 try { 29 Mockito.verify(mock, Mockito.times(1)).quadrat(a); 30 Mockito.verify(mock, Mockito.times(1)).quadrat(b); 31 } catch (WantedButNotInvoked e) { 32 org.Als Bewertungssystem betrachten wir einen separaten Betriebs-systemprozess. Aus konzeptioneller Sicht lädt der Prozess drei verschiedene Komponenten und führt sie aus (vgl. Abbildung 5). Wir gehen davon aus, dass alle Komponenten aus Java Bytecode bestehen, die von derselben JVM-Instanz geladen werden: 3 http://code.google.com/p/mockito/ 4 Zur Funktionsweise der auf der ersten Blick verwirrenden Aufrufsyntax folgt eine kurze Erläuterung: Mockito.mock erzeugt ein Objekt einer zur Laufzeit mit cglib (http://cglib.sourceforge. net/) erzeugten Subklasse von Quadrat. Das wie ein normaler Methodenaufruf aussehende stub.quadrat(a) führt mockito-intern dazu, dass eine ID des aktuell ausgeführten Threads in</cell></row></table><note>mock(Quadrat.class); 15 Mockito.when(stub.quadrat(a)).thenReturn(a*a); 16 Mockito.when(stub.quadrat(b)).thenReturn(b*b); 17 double c= ReflectionSupport.invokeStatic( 18 getClassForName("Hypo"),double.class,"hypo",stub,a,b); 19org.junit.Assert.assertEquals("hypo(q,"+a+","+b+")="+c+ 20 " (erwartet: "+cExpected+")", cExpected, c, 1Ejunit.Assert.fail("hypo muss die Quadrierung "+ 33 "an den Quadrat-Parameter delegieren"); 34 }2.4 Test Doubles: Stubs und MocksÄhnlich ließe sich nun der Bewertungsaspekt (2) untersuchen, indem eine QuadratImpl-Musterlösung als Parameter an die studentische hypo-Methode übergeben wird. Die erneute Verwendung einer u. U. fehlerhaften studentischen QuadratImpl-Klasse würde die Bewertung des Aspekts (2) negativ verzerren. Der Fehler würde in zwei Bewertungsaspekten "gezählt". Als Alternative zu einer eigenen Musterlösung kann man ein Test Double [Me07] einsetzenein Platzhalter-Objekt, mit dem ein untersuchter Programmteil (das sog. system under test -kurz SUT) während des Tests interagiert. Stub-Objekte sind Test Doubles, die vorgefertigte Antworten an das SUT liefern. Der Bewertungsaspekt (3) lässt sich schließlich durch eine weitere Test Double Variante, die sog. Mock-Objekte realisieren (vgl. Abbildung 4). Ein Mock-Objekt wird in Zeile 25 erstellt, welches die Quadrat-Schnittstelle implementiert. Da uns bei diesem Bewertungsaspekt das Berechnungsergebnis nicht interessiert, programmieren wir keine vorbereiteten Antworten. Stattdessen befragen wir das Mock-Objekt nach Ausführung des SUT in Zeile 29f, ob es Aufrufe mit den angegebenen Parametern erhalten hat.3. Sicherheit des BewertungssystemsDer Ansatz, studentische Lösungen dynamisch zu analysieren, erfordert die Ausführung des studentischen Codes. Im Unterschied zu herkömmlichen Software-Tests, wo Tester und Autor einander vertrauen (bei Unit-Tests oft sogar dieselbe Person sind), wo also die Testumgebung vom zu testenden System kein böswilliges Verhalten zu befürchten hat, ist dies beim Test von studentischen Einreichungen anders. Hier muss mit Angriffen des getesteten Codes auf die Testumgebung gerechnet werden. Einige Angriffsbeispiele stellt Abschnitt 3.4 vor. Dazu kommen unabsichtliche Programmierfehler in weitaus größerem Umfang als bei Tests professioneller Software. Schutzmaßnahmen gegen solche Angriffe sind daher unabdingbar. In diesem Abschnitt wollen wir konkrete Bedrohungen und Gegenmaßnahmen beleuchten. 3.1 Schutzbereiche einer Datenstruktur zusammen mit dem stub-Objekt und dem Wert a abgelegt wird. Der Rückgabewert von stub.quadrat(a) wird zwar an Mockito.when weiter gereicht, dort jedoch nicht ausgewertet. Stattdessen weist die ID des aktuell ausführenden Threads den Weg zum soeben abgelegten stub-Objekt.</note></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_4"><head>Tabelle 1: Betrachtete Merkmale der Komponenten-Autoren Nr. Merkmal Ausprägungs- grad 7 für …</head><label></label><figDesc></figDesc><table><row><cell>Komponente, die in der Regel von Lehrkräften oder Hilfspersonal</cell><cell></cell><cell></cell><cell></cell></row><row><cell>erstellt wird, ist weniger kritisch, den AutograderCode erachten</cell><cell></cell><cell></cell><cell></cell></row><row><cell>wir als Komponente mit dem geringsten Bedrohungspotential.</cell><cell></cell><cell></cell><cell></cell></row><row><cell cols="5">Um das Bedrohungspotential 6 der einzelnen Komponenten</cell></row><row><cell cols="5">einschätzen zu können, betrachten wir zunächst die in Tabelle 1</cell></row><row><cell cols="5">aufgeführten Merkmale der Komponenten-Autoren. Die beiden</cell></row><row><cell cols="5">ersten Merkmale begünstigen bei hoher Ausprägung unabsichtlich</cell></row><row><cell cols="5">herbeigeführte Bedrohungen, das dritte Merkmal begünstigt</cell></row><row><cell cols="5">absichtlich herbeigeführte Bedrohungen, das vierte Merkmal</cell></row><row><cell cols="2">begünstigt jede Art von Bedrohung.</cell><cell></cell><cell></cell></row><row><cell></cell><cell></cell><cell cols="2">Autograder-Core Assignment-Grader</cell><cell>Submission</cell></row><row><cell>1</cell><cell>Geringe Programmiererfahrung</cell><cell>-</cell><cell cols="2">-+</cell></row><row><cell>2</cell><cell>Geringe Bereitschaft, Zeit für die korrekte Pro-grammierung der Komponente aufzuwenden</cell><cell cols="3">-0 +</cell></row><row><cell>3</cell><cell>"Kriminelle Energie", d. h. Bereitschaft, Bedrohungen absichtlich herbei zu führen.</cell><cell>-</cell><cell cols="2">-+</cell></row><row><cell>4</cell><cell>Größe der Autorengruppe</cell><cell cols="3">-0 +</cell></row><row><cell cols="5">Vor diesem Hintergrund erwarten wir von der Submission-Kom-</cell></row><row><cell cols="5">ponente das größte Bedrohungspotential. Die AssignmentGrader-</cell></row></table></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_6"><head></head><label></label><figDesc>Wenn wir davon ausgehen, dass Submission-Code in wenigstens einem Verzeichnis Schreibrechte eingeräumt werden müssen, ist dieser denial of service Angriff mit Mitteln der Java Sicherheitsarchitektur unseres Wissens nicht abwehrbar. Hier müssen dem die JVM beherbergenden Betriebssystemprozess Ressourcen in begrenztem Maße zugeteilt werden. Beispielsweise in Form einer separaten Festplattenpartition oder in Form einer Datei begrenzter Größe, die als loopback device verwendet wird. Ähnlich müssen die Ressourcen Hauptspeicher und CPU-Zeit durch die Umgebung der JVM begrenzt werden, etwa über einen Parameter zum maximalen Speicherverbrauch beim JVM-Start bzw. mit Hilfe des Linuxkommandos timeout.</figDesc><table /></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_7"><head>Abbildung 6: Aufrufstapel und resultierende Rechte (Beispiel) Abbildung 7: Privilegierter Callback eines Test Doubles Damit</head><label></label><figDesc>Programmcode eines eingeschränkten Anwendungsbereichs darf durch Aufruf einer Operation des Systembereichs selbstverständlich keine zusätzlichen Rechte erlangen. Die JVM ermittelt daher die Schnittmenge der Rechte aller am Aufrufstapel beteiligten Schutzbereiche, um eine potentiell bedrohliche Operation zu überprüfen [Go13]. Die Aufrufreihenfolge zur Laufzeit ist in der Regel Code des Systembereichs Rechte (bspw. Einlesen von Font-Dateien zwecks Erzeugung einer Ausgabe) erhalten kann, die aufrufender Anwendungsbereichs-Code nicht besitzt, gibt es 11 Rückwärts gewandte Aufrufe von Methoden des Autograder-Core aus dem AssignmentGrader heraus sind ebenfalls denkbar, sind jedoch hier nicht Gegenstand der Betrachtung. in Java den doPrivileged-Aufruf. Ein solcher Aufruf wirkt als Abbruchskriterium bei der Bildung der o. g. Rechte-Schnittmenge. Oberhalb des doPrivileged-Aufrufs am Aufrufstapel beteiligte Schutzbereiche werden nicht berücksichtigt. Wäre etwa im Beispiel der Abbildung 6 der Aufruf der Methode d ein privilegierter Aufruf, würde die resultierende Schnittmenge die Rechte {2, 4} umfassen. Beim Einsatz von Test Doubles ruft Submission-Code Test Doubles des AssignmentGrader-Schutzbereichs auf (vgl. Aufruf der Methode h in Abbildung 7). Ohne besondere Vorkehrungen würde der Code im Test Double mit den Rechten der Schnittmenge (AutograderCore ∩ AssignmentGrader ∩ Submission) ausgeführt, also der Rechtemenge {4}. Der von mockito erzeugte Bytecode eines Test Doubles ruft jedoch Methoden der mockito Bibliothek auf (Methode i), die weitgehende Rechte erfordern, u. a. das sehr potente Recht java.lang.reflect.ReflectPermission "suppressAccessChecks", welches den Zugriff auf private und protected member einer Klasse erlaubt (in Abbildung 7 in der Spalte "Recht 5" vorstellbar). Eine Lösung kann nun nicht sein, dem Submission-Schutzbereich alle Rechte zu gewähren, die das Test Double benötigt. Mindestens das Beispiel in Abschnitt 3.4.2.5 spricht dagegen. Wäre der Aufruf der Methode h privilegiert, würden die Methoden h und i mit der Rechtemenge {2, 4, 5} ausgeführt. Leider hat der Autor des AssignmentGraders keine Möglichkeit, den Test Double-Aufruf privilegiert zu gestalten. Die Programmierschnittstelle von mockito, wie wir sie in Abschnitt 2.4 kennen gelernt haben, ermöglicht keine privilegierten Test Doubles. Der eigentliche Methodenaufruf findet im Submission-Code statt, der nicht im Einflussbereich des AssignmentGrader-Autors steht.</figDesc><table><row><cell>4.2 Sicherheitsimplikationen durch Test</cell></row><row><cell>Doubles</cell></row></table><note>11 AutograderCore → AssignmentGrader → Submission (vgl. Abbildung 6). Mit zunehmender Aufruftiefe stehen geringere Rechte zur Verfügung.</note></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_8"><head>Abbildung 8: Proxy-Klasse für ein Test Double von Quadrat Die</head><label></label><figDesc>vorgeschlagene Lösung besteht nun darin, eine Proxy 12 -Klasse in der AssignmentGrader-Komponente zu erstellen, die ein Test Double umhüllt. Beispielhaft ist in Abbildung 8 das Quadrat-Interface und das zugehörige, mit Mockito.mock erzeugte Test Double 13 zu sehen.</figDesc><table /><note>Die Proxy-Klasse besitzt genau die gleiche Schnittstelle wie das Original (Quadrat) und eine dauerhafte Referenz zum Test Double Objekt. Die Implementierung der quadrat-Methode der Proxy-Klasse besteht nun aus einem privilegierten Aufruf von TestDouble&lt;Quadrat&gt;.quadrat. 12 http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Pro xy.html 13 Der von mockito erzeugten Klasse haben wir hier für Darstellungszwecke einen Namen gegeben. In Wirklichkeit ist die erstellte Klasse aus Benutzersicht anonym.</note></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_9"><head></head><label></label><figDesc>Die zentrale Operation (vgl. Abschnitt 2.4) bei der Nutzung von mockito ist die generische Methode Mockito.mock(Class&lt;T&gt; c) 14 . Sie liefert ein Test Double vom Basistyp T, für das alle Methoden der Klasse T aufrufbar sind. Das Test Double wird im weiteren Verlauf von Methoden wie Mockito.when oder Mockito.verify verwendet. An dieser Art des Aufrufs von mockito soll sich durch die beschriebene Sicherheitsanforderung nichts ändern. Einzig der Name der Einstiegsklasse Mockito soll nun MockitoWrap heißen. Die vollständige Beschreibung von MockitoWrap würde den Rahmen dieses Aufsatzes sprengen. Wir nennen nur einige grundlegende Entwurfsideen, die vermutlich in ähnlicher Form auf andere Mock-Frameworks übertragen werden können. MockitoWrap wird im Zuge der Erstellung neuer Programmieraufgaben sukzessive an der Hochschule Hannover weiter entwickelt. Entwurfsidee 1: Sei Class&lt;T&gt; c der Typ, für den ein Test Double erstellt werden soll. Statt direkt Mockito.mock(c) aufzurufen, soll der Wrapper genutzt werden: MockitoWrap.mock(c). Der Wrapper delegiert den Aufruf an das Original (T td=Mockito.mock(c)) und erstellt dann ein Proxy-Objekt für das Test Double td. Das Proxy-Objekt erhält als Konstruktorparameter ein Objekt einer neuen generischen Klasse MockProxyInvocationHandler&lt;T&gt;, die von InvocationHandler 15 erbt. MockProxyInvocationHandler&lt;T&gt; besitzt als Instanzattribute Referenzen auf das Test Double td und dessen Klasse c 16 , so dass stets vom Proxy-Objekt zum Test Double navigiert werden kann. Entwurfsidee 2: Die Methode MockProxyInvocationHandler&lt;T&gt;. invoke delegiert den Methodenaufruf innerhalb einer Privileged Action 17 an das Test Double td.</figDesc><table /></figure>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="1" xml:id="foot_0">Über diese nicht abschließende Aufzählung hinaus sind selbstverständlich viele weitere Schnittstellen denkbar (Umgebungsvariable, Audio/Video, Netzwerk, etc.).</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="5" xml:id="foot_1">In der Praxis entspricht jede Komponente einem jar-Archiv oder jeweils einer Menge von jar-Archiven. Jedem jar-Archiv wird ein Satz von Rechten zugeordnet.</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="6" xml:id="foot_2">Wir meinen hiermit das, was in etablierten Risikoschätzmethoden wie[oV13]  "likelihood" genannt wird.</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="7" xml:id="foot_3">7 Legende: -=gering, 0=mittel, +=hoch</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="8" xml:id="foot_4">Weitere s. z. B. http://docs.oracle.com/javase/7/docs/technotes/ guides/security/permissions.html</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="9" xml:id="foot_5">Noch dazu muss immer wieder mit neu entdeckten Sicherheitslücken in der Java Sandbox gerechnet werden.</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="14" xml:id="foot_6">http://docs.mockito.googlecode.com/hg/latest/index.html?org/ mockito/Mockito.html</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="15" xml:id="foot_7">http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Invo cationHandler.html</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="16" xml:id="foot_8">Type erasure bei Java Generics macht den Einsatz dieses zweitgenannten Instanzattributs notwendig.</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="17" xml:id="foot_9">http://docs.oracle.com/javase/7/docs/api/java/security/Privi legedAction.html</note>
		</body>
		<back>

			<div type="acknowledgement">
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.">Test Doubles bei aktivem Securitymanager</head><p>Das vorangegangene Kapitel hat motiviert, dass der Einsatz der Java Securitymanagers sinnvoll ist, um reale Bedrohungen abzuwenden. Die durch den Einsatz des Securitymanagers resultierenden Auswirkungen auf den Einsatz von Test Doubles sind Gegenstand des nun folgenden Kapitels.</p></div>
			</div>

			<div type="references">

				<listBibl>

<biblStruct xml:id="b0">
	<monogr>
		<title/>
		<author>
			<persName><surname>Literaturverzeichnis</surname></persName>
		</author>
		<imprint/>
	</monogr>
</biblStruct>

<biblStruct xml:id="b1">
	<analytic>
		<title level="a" type="main">Using Test-Driven Development in the Classroom: Providing Students with Automatic, Concrete Feedback on Performance</title>
		<author>
			<persName><forename type="first">S</forename><surname>Edwards</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">Proc. Int&apos;l Conf. Education and Information Systems: Technologies and Applications (EISTA &apos;03)</title>
				<meeting>Int&apos;l Conf. Education and Information Systems: Technologies and Applications (EISTA &apos;03)</meeting>
		<imprint>
			<date type="published" when="2003-08">Aug. 2003</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b2">
	<monogr>
		<title level="m" type="main">Java TM SE Platform Security Architecture</title>
		<author>
			<persName><forename type="first">L</forename><surname>Gong</surname></persName>
		</author>
		<ptr target="Abruf13.09.2013" />
		<imprint/>
	</monogr>
</biblStruct>

<biblStruct xml:id="b3">
	<monogr>
		<title level="m" type="main">Practical Unit Testing with JUnit and Mockito</title>
		<author>
			<persName><forename type="first">T</forename><surname>Kaczanowski</surname></persName>
		</author>
		<imprint>
			<date type="published" when="2013">2013</date>
			<publisher>Verlag Tomasz Kaczanowski</publisher>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b4">
	<analytic>
		<title level="a" type="main">Web-basierte Programmierpraktika mit Praktomat</title>
		<author>
			<persName><forename type="first">J</forename><surname>Krinke</surname></persName>
		</author>
		<author>
			<persName><forename type="first">M</forename><surname>Störzer</surname></persName>
		</author>
		<author>
			<persName><forename type="first">A</forename><surname>Zeller</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="j">Softwaretechnik-Trends</title>
		<imprint>
			<biblScope unit="volume">22</biblScope>
			<biblScope unit="issue">3</biblScope>
			<date type="published" when="2002-10">October 2002</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b5">
	<monogr>
		<title level="m" type="main">xUnit Test Patterns: Refactoring Test Code</title>
		<author>
			<persName><forename type="first">G</forename><surname>Meszaros</surname></persName>
		</author>
		<imprint>
			<date type="published" when="2007">2007</date>
			<publisher>Addison-Wesley Longman</publisher>
			<pubPlace>Amsterdam</pubPlace>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b6">
	<monogr>
		<author>
			<persName><forename type="first">.</forename><forename type="middle">V</forename></persName>
		</author>
		<ptr target="https://www.owasp.org/index.php?title=OWASP_Risk_Rating_Methodology&amp;oldid=158022,Abruf13." />
		<title level="m">OWASP Risk Rating Methodology</title>
				<imprint>
			<date type="published" when="2013-09">09.2013</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b7">
	<analytic>
		<title level="a" type="main">Enabling Graph Transformations on Program Code</title>
		<author>
			<persName><forename type="first">M</forename><surname>Striewe</surname></persName>
		</author>
		<author>
			<persName><forename type="first">M</forename><surname>Balz</surname></persName>
		</author>
		<author>
			<persName><forename type="first">M</forename><surname>Goedicke</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">Proceedings of the Fourth International Workshop on Graph-Based Tools (GraBaTs 2010)</title>
				<meeting>the Fourth International Workshop on Graph-Based Tools (GraBaTs 2010)<address><addrLine>Enschede, Netherlands</addrLine></address></meeting>
		<imprint>
			<date type="published" when="2010">2010</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b8">
	<monogr>
		<author>
			<persName><forename type="first">A</forename><surname>Spillner</surname></persName>
		</author>
		<author>
			<persName><forename type="first">T</forename><surname>Linz</surname></persName>
		</author>
		<title level="m">Basiswissen Softwaretest (3. Auflage)</title>
				<meeting><address><addrLine>Heidelberg, Germany</addrLine></address></meeting>
		<imprint>
			<publisher>dpunkt</publisher>
			<date type="published" when="2005">2005</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b9">
	<analytic>
		<title level="a" type="main">Evaluation automatisierter Programmbewertung bei der Vermittlung der Sprachen Java und SQL mit den Gradern &quot;aSQLg&quot; und &quot;Graja&quot; aus studentischer Perspektive</title>
		<author>
			<persName><forename type="first">A</forename><surname>Stöcker</surname></persName>
		</author>
		<author>
			<persName><forename type="first">S</forename><surname>Becker</surname></persName>
		</author>
		<author>
			<persName><forename type="first">R</forename><surname>Garmann</surname></persName>
		</author>
		<author>
			<persName><forename type="first">F</forename><surname>Heine</surname></persName>
		</author>
		<author>
			<persName><forename type="first">C</forename><surname>Kleiner</surname></persName>
		</author>
		<author>
			<persName><forename type="first">O</forename><forename type="middle">J</forename><surname>Bott</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">Proceedings DeLFI</title>
				<meeting>DeLFI</meeting>
		<imprint>
			<date type="published" when="2013">2013</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b10">
	<analytic>
		<title level="a" type="main">Supporting student-written tests of GUI programs</title>
		<author>
			<persName><forename type="first">M</forename><surname>Thornton</surname></persName>
		</author>
		<author>
			<persName><forename type="first">S</forename><forename type="middle">H</forename><surname>Edwards</surname></persName>
		</author>
		<author>
			<persName><forename type="first">R</forename><forename type="middle">P</forename><surname>Tan</surname></persName>
		</author>
		<author>
			<persName><forename type="first">M</forename><forename type="middle">A</forename><surname>Pérez-Quiñones</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">Proceedings of the 39 th SIGCSE Technical Symposium on Computer Science Education</title>
				<meeting>the 39 th SIGCSE Technical Symposium on Computer Science Education<address><addrLine>New York, NY</addrLine></address></meeting>
		<imprint>
			<publisher>ACM Press</publisher>
			<date type="published" when="2008">2008</date>
			<biblScope unit="page" from="537" to="541" />
		</imprint>
	</monogr>
</biblStruct>

				</listBibl>
			</div>
		</back>
	</text>
</TEI>
