Folien ab 10.3.14

Werbung
2. Unit - Tests
•
•
•
•
•
Annotationen
Varianten von JUnit
Testfälle mit JUnit
Testsuite mit JUnit
Parametrisierte Tests
• Hinweis: Um im Praktikum experimentieren zu können, erst
„wie schreibe ich Tests“ und danach „welche Tests sind
sinnvoll“
• Warnung für dieses und die weiteren Kapitel:
Der Programmcode ist meist ein Beispiel für schlechte
Formatierung; hier erlaubt, um möglichst viele Details auf
einer Folie mit Ihnen zu diskutieren
Software-Qualität
Stephan Kleuker
33
Testfall
• Vor dem Testen müssen Testfälle spezifiziert werden
• Vorbedingungen
– Zu testende Software in klar definierte Ausgangslage bringen
(z. B. Objekte mit zu testenden Methoden erzeugen)
– Angeschlossene Systeme in definierten Zustand bringen
– Weitere Rahmenbedingungen sichern (z. B. HW)
• Ausführung
– Was muss wann gemacht werden (einfachster Fall:
Methodenaufruf)
• Nachbedingungen
– Welche Ergebnisse sollen vorliegen (einfachster Fall:
Rückgabewerte)
– Zustände anderer Objekte / angeschlossener Systeme
Software-Qualität
Stephan Kleuker
34
JUnit
• Framework, um den Unit-Test eines Java-Programms zu
automatisieren
• einfacher Aufbau
• leicht erlernbar
• geht auf SUnit
(Smalltalk) zurück
• mittlerweile für
viele Sprachen
verfügbar (NUnit,
CPPUnit)
Software-Qualität
Stephan Kleuker
35
JUnit - zwei Varianten
JUnit 3.8.x
• entwickelt für „klassisches“ Java vor Java 5
• Testklassen müssen von einer Klasse TestCase erben
• Tests müssen in Testklassen stehen
• gibt einige weitere QS-Werkzeuge, die solche Tests nutzen
bzw. selbst erstellen (gehen nicht mit JUnit 4)
• Ideen leichter auf XUnit-Varianten übertragbar
JUnit 4.x
• nutzt Annotationen
• Tests können in zu testenden Klassen stehen
• etwas flexibler als Junit 3.8.x
Software-Qualität
Stephan Kleuker
36
Einsatz von Annotationen: Weiterverarbeitung
// HelloWorldService.java
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
public class HelloWorldService {
@WebMethod
public String helloWorld() {
return "Hello World!";
}
}
• Annotationen beginnen mit einem @ und können, z. B. von
anderen Programmen zur Weiterverarbeitung genutzt werden
• hier z. B. soll die Erzeugung eines Web-Services durch die
Kennzeichnung relevanter Teile durch Annotationen erfolgen
• Java besitzt seit Version 5 Annotationen, man kann selbst
weitere definieren
Software-Qualität
Stephan Kleuker
37
Syntax von Annotationen
• Annotationen können Parameter haben
• ohne Parameter: @EinfacheAnnotation
• mit einem Parameter @EinAnno(par="Hallo") oder
@EinAnno("Hallo") (bei nur einem Parameter kann der
Parametername weggelassen werden)
• mit mehreren Parametern werden Wertepaare
(Parametername, Wert) angegeben
@KomplexAnno(par1="Hi", par2=42, par3={41,43})
• Annotationen können bei/vor anderen Modifiern (z.B.
public, abstract) bei folgenden Elementen stehen:
− Exemplar- und Klassenvariable
– package
– class, interface, enum − lokale Variablen
− Parameter
– Methode
• Man kann einschränken, wo welche Annotation erlaubt ist
Software-Qualität
Stephan Kleuker
38
Beispiel: Nutzung vordefinierter Annotation
public class Oben {
public void supertolleSpezialmethode(){
System.out.println("Ich bin oben");
}
}
public class Unten extends Oben{
@Override public void superTolleSpezialmethode(){
System.out.println("Ich bin unten");
}
public static void main(String[] s){
Unten u = new Unten();
u.supertolleSpezialmethode();
}
ohne Annotation in Java 1.4:
}
Ich bin oben
Compilermeldung:
..\..\netbeans\Annotationen\src\Unten.java:2: method does not
override a method from its superclass
@Override public void superTolleSpezialmethode(){
1 error
Software-Qualität
Stephan Kleuker
39
Konstruktiver Ansatz
• Testfälle werden in Java programmiert, keine spezielle
Skriptsprache notwendig
• Idee ist inkrementeller Aufbau der Testfälle parallel zur
Entwicklung
– Pro Klasse wird mindestens eine Test-Klasse
implementiert (oder in Klasse ergänzt)
• JUnit ist in Eclipse integriert, sonst muss das Paket junit.jar
zu CLASSPATH hinzugefügt werden.
Software-Qualität
Stephan Kleuker
40
Spezifikationsausschnitt
• Gegeben sei eine Aufzählung mit den folgenden Werten
package verwaltung.mitarbeiter;
public enum Fachgebiet {
ANALYSE, DESIGN, JAVA, C, TEST
}
• Zu entwickeln ist eine Klasse Mitarbeiter, wobei jedes
Mitarbeiterobjekt
– eine eindeutige Kennzeichnung (id) hat
– einen änderbaren Vornamen haben kann
– einen änderbaren Nachnamen mit mindestens zwei Zeichen
hat
– eine Informationssammlung mit maximal drei Fachgebieten
hat, die ergänzt und gelöscht werden können
Software-Qualität
Stephan Kleuker
41
Klasse Mitarbeiter (1/4) - fast korrekt
package verwaltung.mitarbeiter;
import java.util.HashSet;
import java.util.Set;
public class Mitarbeiter {
private int id;
private static int idGenerator = 100;
private String vorname;
private String nachname;
private Set<Fachgebiet> fachgebiete;
public Mitarbeiter(String vorname, String nachname) {
if (nachname == null || nachname.length() < 2)
throw new IllegalArgumentException(
"Nachname mit mindestens zwei Zeichen");
this.vorname = vorname;
this.nachname = nachname;
this.id = idGenerator++;
this.fachgebiete = new HashSet<Fachgebiet>();
} Software-Qualität
Stephan Kleuker
42
Klasse Mitarbeiter (2/4)
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getVorname() { return vorname; }
public void setVorname(String vorname) {
this.vorname = vorname; }
public String getNachname() { return nachname; }
public void setNachname(String nachname) {
this.nachname = nachname;}
public Set<Fachgebiet> getFachgebiete() {
return fachgebiete;}
public void setFachgebiete(Set<Fachgebiet> fachgebiete) {
this.fachgebiete = fachgebiete;
}
Software-Qualität
Stephan Kleuker
43
Klasse Mitarbeiter (3/4)
public void addFachgebiet(Fachgebiet f){
fachgebiete.add(f);
if(fachgebiete.size() > 3){
fachgebiete.remove(f);
throw new IllegalArgumentException(
"Maximal 3 Fachgebiete");
}
}
public void removeFachgebiet(Fachgebiet f){
fachgebiete.remove(f);
}
public boolean hatFachgebiet(Fachgebiet f){
return fachgebiete.contains(f);
}
Software-Qualität
Stephan Kleuker
44
Klasse Mitarbeiter (4/4)
@Override
public int hashCode() { return id; }
@Override
public boolean equals(Object obj) {
if (obj == null || getClass() != obj.getClass())
return false;
Mitarbeiter other = (Mitarbeiter) obj;
return (id == other.id);
}
@Override
public String toString(){
StringBuffer erg = new StringBuffer(vorname+
" "+nachname+" ("+id+")[ ");
for(Fachgebiet f:fachgebiete)
erg.append(f+" ");
erg.append("]");
return erg.toString();
Stephan Kleuker
} Software-Qualität
45
Testen von Hand
public static void main(String... s){
Mitarbeiter m = new Mitarbeiter("Uwe","Mey");
m.addFachgebiet(Fachgebiet.ANALYSE);
m.addFachgebiet(Fachgebiet.C);
m.addFachgebiet(Fachgebiet.JAVA);
System.out.println(m);
m.addFachgebiet(Fachgebiet.TEST);
}
Uwe Mey (100)[ C JAVA ANALYSE ]
Exception in thread "main"
java.lang.IllegalArgumentException: Maximal 3 Fachgebiete
at
verwaltung.mitarbeiter.Mitarbeiter.addFachgebiet(Mitarbei
ter.java:58) at
verwaltung.mitarbeiter.Mitarbeiter.main(Mitarbeiter.java:
99)
Software-Qualität
Stephan Kleuker
46
Anlegen einer Testklasse (1/2)
Software-Qualität
Stephan Kleuker
47
Anlegen einer Testklasse (2/2)
Software-Qualität
Stephan Kleuker
48
Testen mit JUnit
• Tests werden mit Methoden durchgeführt, die mit
Annotation @Test markiert sind
• Testmethoden haben typischerweise keinen Rückgabewert
(nicht verboten)
• Tests stehen typischerweise in eigener Klasse; für Klasse X
eine Testklasse XTest (können auch in zu testender Klasse
stehen)
• Mit Klassenmethoden der Klasse Assert werden gewünschte
Eigenschaften geprüft
Assert.assertTrue("korrekter Vorname"
,m.getVorname().equals("Ute"));
• JUnit steuert Testausführung, Verstöße bei Prüfungen
werden protokolliert
Software-Qualität
Stephan Kleuker
49
Test des Konstruktors und der eindeutigen Id
package verwaltung.mitarbeiter;
import org.junit.Assert;
import org.junit.Test;
public class MitarbeiterTest {
@Test
public void testKonstruktor(){
Mitarbeiter m = new Mitarbeiter("Ute","Mai");
Assert.assertTrue("korrekter Vorname"
,m.getVorname().equals("Ute"));
Assert.assertTrue("korrekter Nachname"
,m.getNachname().equals("Mai"));
}
@Test
public void testEindeutigeId(){
Assert.assertTrue("unterschiedliche ID"
, new Mitarbeiter("Ute","Mai").getId()
!= new Mitarbeiter("Ute","Mai").getId());
}
Software-Qualität
Stephan Kleuker
50
Anmerkungen
• keine gute Idee: mehrere Asserts hintereinander (scheitert
das Erste, wird Zweite nicht betrachtet -> Tests trennen)
• Assert-Methoden haben optionalen ersten String-Parameter
• String kann genauere Informationen über erwartete Werte
enthalten, z. B. über toString-Methoden der beteiligten
Objekte
• generell reicht Assert.assertTrue() aus, gibt viele weitere
Methoden
• Um nicht immer die Klasse Assert angeben zu müssen, kann
man auch (persönlich unschön) folgendes nutzen:
import static org.junit.Assert.*;
Software-Qualität
Stephan Kleuker
51
Ausschnitt: Klassenmethoden von Assert
assertArrayEquals(java.lang.Object[] expecteds,
java.lang.Object[] actuals)
Asserts that two object arrays are equal.
assertEquals(double expected, double actual, double delta)
Asserts that two doubles or floats are equal to within
a positive delta.
assertFalse(boolean condition)
assertNotNull(java.lang.Object object)
assertNull(java.lang.Object object)
assertSame(java.lang.Object expected,
java.lang.Object actual)
Asserts that two objects refer to the same object.
assertThat(T actual, org.hamcrest.Matcher<T> matcher)
Asserts that actual satisfies the condition specified
by matcher.
assertTrue(boolean condition)
fail()
Fails a test with no message.
Software-Qualität
Stephan Kleuker
52
Test-Fixture
• Testfall sieht in der Regel so aus, dass eine bestimmte
Konfiguration von Objekten aufgebaut wird, gegen die der
Test läuft
• Menge von Testobjekten wird als Test-Fixture bezeichnet
• Damit fehlerhafte Testfälle nicht andere Testfälle
beeinflussen können, wird die Test-Fixture für jeden Testfall
neu initialisiert
• In der mit @Before annotierten Methode werden
Exemplarvariablen initialisiert
• In der mit @After annotierten Methode werden wertvolle
Testressourcen wie zum Beispiel Datenbank- oder
Netzwerkverbindungen wieder freigegeben
Software-Qualität
Stephan Kleuker
53
Tests von hatFähigkeit
public class MitarbeiterTest {
Mitarbeiter m1;
@Before
public void setUp() throws Exception {
m1 = new Mitarbeiter("Uwe","Mey");
m1.addFachgebiet(Fachgebiet.ANALYSE);
m1.addFachgebiet(Fachgebiet.C);
m1.addFachgebiet(Fachgebiet.JAVA);
}
@Test
public void testHatFaehigkeit1(){
Assert.assertTrue("vorhandene Faehigkeit"
,m1.hatFachgebiet(Fachgebiet.C));
}
@Test
public void testHatFaehigkeit2(){
Assert.assertTrue("nicht vorhandene Faehigkeit"
,!m1.hatFachgebiet(Fachgebiet.TEST));
} Software-Qualität
Stephan Kleuker
54
Testablaufsteuerung (1/3)
wird einmal für alle Tests vor
public class AblaufAnalyse {
allen Tests ausgeführt (static !)
@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("setUpBeforeClass");
}
wird einmal für alle Tests vor
nach Tests ausgeführt (static !)
@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("tearDownAfterClass");
}
@Before
public void setUp() throws Exception {
System.out.println("setUp");
}
Software-Qualität
Stephan Kleuker
55
Testablaufsteuerung (2/3)
@After
public void tearDown() throws Exception {
System.out.println("tearDown");
}
@Test
public void test1(){
System.out.println("test1");
}
@Test
public void test2(){
System.out.println("test2");
}
}
Software-Qualität
Stephan Kleuker
56
Testablaufsteuerung (3/3)
setUpBeforeClass
setUp
test1
tearDown
setUp
test2
tearDown
tearDownAfterClass
Software-Qualität
Stephan Kleuker
57
Testen von Exceptions (1/3)
• Erinnerung: Exception bei vierter Fähigkeit
• Variante 1: Exception in @Test-Annotation festhalten
@Test(expected=IllegalArgumentException.class)
public void testAddFaehigkeit1(){
m1.addFachgebiet(Fachgebiet.TEST);
}
• Falls Exception nicht geworfen wird:
• Vorteil: sehr kompakte Beschreibung
• Nachteil: keine detaillierte Analyse der Exception möglich
Software-Qualität
Stephan Kleuker
58
Testen von Exceptions (2/3)
• Variante 2: „klassisch“ man markiert Stellen, von denen man
erwartet, dass sie nicht ausgeführt werden
@Test
public void testAddFaehigkeit1a(){
try{
m1.addFachgebiet(Fachgebiet.TEST);
Assert.fail("fehlende Exception");
}catch(IllegalArgumentException e){
Assert.assertNotNull(e.getMessage()); // oder leer
}catch(Exception e){
Assert.fail("unerwartet "+e);
}
}
Software-Qualität
Stephan Kleuker
59
Testen von Exceptions (3/3)
• wenn keine Exception auftreten soll
@Test
public void testAddFaehigkeit2(){
m1.addFachgebiet(Fachgebiet.C);
}
@Test
public void testAddFaehigkeit2a(){
try{
m1.addFachgebiet(Fachgebiet.C);
}catch(Exception e){
Assert.fail("unerwartet "+e);
}
}
Software-Qualität
Stephan Kleuker
60
Ausblick: langfristige Testnutzung
• Bisher geschriebene Tests werden typischerweise von
Entwicklern geschrieben
• Tests müssen archiviert und bei jedem Release neu
ausführbar sein
• Beispiel: unerfahrener Neuling ersetzt
private List<Fachgebiet> fachgebiete
= new ArrayList<Fachgebiet>();
Software-Qualität
Stephan Kleuker
61
Testorganisation
Für große Projekte sind folgende Wünsche bzgl. der Tests
typisch:
a) mehrere Testklassen sollen zusammen laufen können
b) man möchte Tests flexibel kombinieren können;
Testwiederholung soll davon abhängen, welche Klassen
betroffen sein können [schwierige Weissagung]
c) man möchte Tests automatisiert ablaufen lassen können
möglich z. B.:
– JUnit hat Klassen zum einfachen Start von der Konsole
aus
– Nutzung eines cron-Jobs
zu a) und b) folgende Folien: Tests zusammenfassen zu
TestSuites
Software-Qualität
Stephan Kleuker
62
Tests zusammenfassen (1/3) - weitere Testklasse
package verwaltung.mitarbeiter;
import org.junit.Assert;
import org.junit.Test;
public class Mitarbeiter2Test {
@Test
public void testHinzuUndWeg(){
Mitarbeiter m = new Mitarbeiter("Hu","Go");
m.addFachgebiet(Fachgebiet.C);
m.addFachgebiet(Fachgebiet.C);
m.removeFachgebiet(Fachgebiet.C);
Assert.assertFalse(m.hatFachgebiet(Fachgebiet.C));
}
}
Software-Qualität
Stephan Kleuker
63
Tests zusammenfassen (2/3) - einzelne TestSuite
• Anmerkung: Aufbau nicht ganz intuitiv
package verwaltung.mitarbeiter;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;;
@RunWith(Suite.class)
@SuiteClasses({Mitarbeiter2Test.class,
MitarbeiterTest.class})
public class MitarbeiterAllTest {
// hier stehen keine Tests !
}
Software-Qualität
Stephan Kleuker
64
Tests zusammenfassen (3/3) - Suite in Suite
package verwaltung;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import verwaltung.mitarbeiter.MitarbeiterAllTest;
@RunWith(Suite.class)
@SuiteClasses({MitarbeiterAllTest.class})
public class VerwaltungAllTest {}
Software-Qualität
Stephan Kleuker
65
Test weiterer Anforderung (1/2)
• Anforderung „einen änderbaren Nachnamen mit
mindestens zwei Zeichen hat“
@Test
public void testAddKonstruktor2(){
try{
new Mitarbeiter(null,null);
Assert.fail("fehlt Exception ");
}catch(IllegalArgumentException e){
}
}
@Test
public void testAddKonstruktor3(){
try{
new Mitarbeiter(null,"X");
Assert.fail("fehlt Exception ");
}catch(IllegalArgumentException e){
}
Stephan Kleuker
} Software-Qualität
66
Test weiterer Anforderung (2/2)
• fehlt noch: Nachnamenänderung prüfen
@Test
public void testSetNachname1(){
m1.setNachname("Mai");
Assert.assertEquals(m1.getNachname(), "Mai");
}
@Test // hier wird ein Fehler gefunden!
public void testSetNachname2(){
try{
m1.setNachname("X");
Assert.fail("fehlt Exception ");
}catch(IllegalArgumentException e){
}
}
Software-Qualität
Stephan Kleuker
67
Test von equals
@Test
public void testEquals1(){
Assert.assertTrue(m1.toString(),m1.equals(m1));
}
@Test
public void testEquals2(){
Assert.assertFalse(m1
.equals(new Mitarbeiter("Ute","Mey")));
}
@Test
public void testEquals3(){
Mitarbeiter m2 = new Mitarbeiter("Ufo","Hai");
m2.setId(m1.getId());
Assert.assertTrue(m1.equals(m2));
}
Software-Qualität
Stephan Kleuker
68
Was wann testen?
• Beispiel zeigt bereits, dass man sehr viele sinnvolle Tests
schreiben kann
• Frage: Wieviele Tests sollen geschrieben werden?
– jede Methode testen
– doppelte Tests vermeiden
– je kritischer eine SW, desto mehr Tests
– Suche nach Kompromissen: Testkosten vs Kosten von
Folgefehlern
– ein Kompromiss: kein Test generierter Methoden
(Konstruktoren, get, set, equals, hashCode)
• (nächster Block, sinnvolle Testerstellung)
Software-Qualität
Stephan Kleuker
69
Tests ein/und ausschalten
• verschiedene Ansätze, Stellen zu markieren, die noch
entwickelt werden (//TODO)
• häufiger kann man Tests schreiben, bevor Implementierung
vorliegt (-> Design by Concept durch Interfaces)
• Tests können auch sonst so inaktiv geschaltet werden
@Ignore("erst im Release 42.0 lauffähig")
@Test
public void testChefIstNummer1(){
Mitarbeiter chef = new Mitarbeiter("Ego","Ich");
Assert.assertEquals("Nr.1", chef.getId(),1);
}
Software-Qualität
Stephan Kleuker
70
Gefahr von Endlostests
• Tests laufen nacheinander, endet einer nicht, werden andere
nicht ausgeführt
@Test(timeout=2000)
public void testGodot(){
while (!m1.getFachgebiete().isEmpty())
Assert.assertFalse(m1.hatFachgebiet(Fachgebiet.TEST));
}
Software-Qualität
Stephan Kleuker
71
Parametrisierte Tests
• bereits gesehen: häufig wird eine Methode mit
verschiedenen Parametern getestet
• das Schreiben gleichartiger Tests mit ähnlichen Parametern
ist langweilig und zeitaufwändig
• Ansatz: Testdaten irgendwo kompakt speichern und für
Testfälle einlesen
• Lösung in JUnit über mit @Parameter annotierte Methode,
die eine Sammlung von Daten liefert
Software-Qualität
Stephan Kleuker
72
Beispiel: Parametrisierte Tests (1/2)
package verwaltung.mitarbeiter;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(value = Parameterized.class)
public class Mitarbeiter3Test {
@Parameters
public static Collection<Object[]> daten() {
Object[][] testdaten = {
{Fachgebiet.ANALYSE, Fachgebiet.C, Fachgebiet.C}
,{Fachgebiet.ANALYSE, Fachgebiet.C, Fachgebiet.ANALYSE}
,{Fachgebiet.C, Fachgebiet.C, Fachgebiet.C} };
return Arrays.asList(testdaten);
}
Software-Qualität
Stephan Kleuker
73
Beispiel: Parametrisierte Tests (2/2)
private Mitarbeiter m1;
private Fachgebiet hat;
public Mitarbeiter3Test(Fachgebiet f1, Fachgebiet f2,
Fachgebiet f3) {
m1 = new Mitarbeiter("Oh", "Ha");
m1.addFachgebiet(f1);
m1.addFachgebiet(f2);
hat = f3;
}
@Test
public void testHat() {
Assert.assertTrue(m1.hatFachgebiet(hat));
}
}
Software-Qualität
Stephan Kleuker
74
Parametrisierung genauer angesehen
public class ParametrisierterTest{
tpa1
tpb1
tpa2
…
tpan
tpb2
…
tpbn
tpk2
…
tpkn
Object[]
entspricht einer
Parameterliste
Collection<Object[]>
...
tpk1
public class ParametrisierterTest(par1, par2, ...,parn){...
• Parameter tpa (Zeile) gehören zu einem Test und können im
Test beliebig genutzt werden (Berechnung, Prüfung, …)
Software-Qualität
Stephan Kleuker
75
Einschränkungen bei Parametrisierung
• Parameter-Methode muss Collection<Object[]> liefern
@Parameters
public static Collection<Object[]> data() {...
• enthaltene Object[] müssen gleich groß sein
• Typen der Array-Elemente müssen zum Konstruktor des
Tests passen
• Man kann in data() auf Dateien zugreifen
• Es gibt kreative Tricks, z. B. dynamische Arraygrößen mit
null-Werten zu ermöglichen
Software-Qualität
Stephan Kleuker
76
Parameter aus Datei testen (1/4) - Erinnerung
• Einfaches Speichern in XML über Serializable
• ergänzen in Mitarbeiter:
import java.io.Serializable;
public class Mitarbeiter implements Serializable{
private static final long serialVersionUID =
458076069326042941L;
public Mitarbeiter(){ // nur für Serialisierung
fachgebiete = new HashSet<Fachgebiet>();
// man bedenke Nachnamenproblem
}
• Anmerkung: Java kann auch mit anderen Dateien (z. B. .csv)
arbeiten
Software-Qualität
Stephan Kleuker
77
Parameter aus Datei testen (2/4) – Daten erzeugen
public class Datenerzeugung {
private final String DATEI="daten.xml";
public Datenerzeugung() throws FileNotFoundException{
XMLEncoder out = new XMLEncoder(new BufferedOutputStream(
new FileOutputStream(DATEI)));
out.writeObject(new Mitarbeiter("Hai","Wo"));
out.writeObject(Fachgebiet.TEST);
out.writeObject(true);
out.writeObject(Fachgebiet.TEST);
out.writeObject(new Mitarbeiter("Su","Se"));
out.writeObject(Fachgebiet.TEST);
out.writeObject(false);
out.writeObject(Fachgebiet.C);
out.close();
}
public static void main(String[] args) throws
FileNotFoundException {
new Datenerzeugung();
}
}
Software-Qualität
Stephan Kleuker
78
Parameter aus Datei testen (3/4) – Daten lesen
@Parameters public static Collection<Object[]> daten()
throws FileNotFoundException {
List<Object[]> ergebnis = new ArrayList<Object[]>();
XMLDecoder in = new XMLDecoder(new BufferedInputStream(
new FileInputStream(DATEI)));
boolean neuerWert = true;
while (neuerWert) {
Object[] tmp = new Object[3];
try {
Mitarbeiter m = (Mitarbeiter) in.readObject();
m.addFachgebiet((Fachgebiet) in.readObject());
tmp[0] = m;
tmp[1] = (Boolean) in.readObject();
tmp[2] = (Fachgebiet) in.readObject();
ergebnis.add(tmp);
} catch (ArrayIndexOutOfBoundsException e) {
neuerWert = false;
}
}
in.close(); return ergebnis;
Stephan Kleuker
79
} Software-Qualität
Parameter aus Datei testen (4/4) – Testen
public class Mitarbeiter4Test {
static private final String DATEI = "daten.xml";
@Parameters ... // letzte Folie
private Mitarbeiter m;
private boolean erwartet;
private Fachgebiet pruef;
public Mitarbeiter4Test(Mitarbeiter m, Boolean b,
Fachgebiet f) {
System.out.println(m + " : " + b + " : " + f);
this.m = m;
this.erwartet = b;
Hai Wo (100)[ TEST ] : true : TEST
this.pruef = f;
Su Se (101)[ TEST ] : false : C
}
@Test
public void testHat() {
Assert.assertTrue(m.hatFachgebiet(pruef)==erwartet);
}
}
Software-Qualität
Stephan Kleuker
80
JUnit - Erweiterungen
• Beispiel: Klasse Runner zur Teststeuerung
• Aus: http://junit.sourceforge.net/javadoc/org/junit/runner/Runner.html
„A Runner runs tests and notifies a RunNotifier of significant events as it
does so. You will need to subclass Runner when using RunWith to
invoke a custom runner. When creating a custom runner, in addition to
implementing the abstract methods here you must also provide a
constructor that takes as an argument the Class containing the tests.
The default runner implementation guarantees that the instances of the
test case class will be constructed immediately before running the test
and that the runner will retain no reference to the test case instances,
generally making them available for garbage collection.“
• Fehlt noch: Möglichkeit, Tests nur durchzuführen, wenn
andere Tests vorher erfolgreich waren (erst Login testen,
dann Funktionalität)  Variante TestNG
Software-Qualität
Stephan Kleuker
81
Herunterladen