• Save
Test-Driven-Development mit JUnit 4
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

Test-Driven-Development mit JUnit 4

  • 10,026 views
Uploaded on

Schulung über die testgetriebene Software-Entwicklung mit dem Schwerpunkt JUnit 4.

Schulung über die testgetriebene Software-Entwicklung mit dem Schwerpunkt JUnit 4.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
10,026
On Slideshare
9,814
From Embeds
212
Number of Embeds
7

Actions

Shares
Downloads
1
Comments
0
Likes
5

Embeds 212

http://dinkla.net 106
http://www.slideshare.net 37
http://www.dinkla.net 35
http://www.dinkla.com 28
http://dinkla.com 4
http://translate.googleusercontent.com 1
http://www.slideee.com 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • OPT evtl. Diagram Tiefe und Breite
  • lib/junit-4.4.jar:build/classes:../JUnit-Base/build/junit-schulung-base.jar
  • Assert ist in Java 1.4 bereits enthalten
  • TODO Reihenfolge der Ausführung
  • TODO Running Fortgeschritten
    Einzelne mit <test>
  • TODO
  • brittleness Brüchigkeit, Sprödigkeit, Zerbrechlichkeit, Morschheit
  • Zustandslos .NET ?
  • TODO Warnung, dass theo nicht möglich
  • TODO
  • TODO nanoTime
  • TODO
  • TODO 1.1 lassen weg Fehlalarm
  • TODO Webseiten URLS
  • TODO

Transcript

  • 1. Schulung „Testgetriebene Entwicklung mit JUnit 4“ © 2008 - 2009 Jörn Dinkla joern@dinkla.com http://www.dinkla.com © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 2. Vorstellung • Dipl.-Inform. Jörn Dinkla • Schwerpunkte • Java Entwicklung (J2SE, JEE) • Moderne Programmiersprachen • Groovy, Ruby, Haskell, Scala • Modellgetriebene Entwicklung • Automatisierung • Eclipse • Plugin-Entwicklung • CUDA, OpenCL • Hobbies • Musik, Literatur © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 2
  • 3. Überblick © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 4. Überblick: JUnit und Testwerkzeuge • Grundlagen des Testen • JUnit • Tests und Design • Standards • Nebenläufigkeit • Erweiterungen von JUnit • TestNG • Akzeptanztests mit Fit und FitNesse • Zwischendurch • Hands-on • Gemeinsam entwickeln © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 4
  • 5. Grundlagen des Testens © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 6. Software-Qualität wird vernachlässigt • Aus der PC Welt vom April 2008 • „Software-Hersteller haben häufig nur ein Ziel: Ihre Anwendungen schnell zu entwickeln und Projekte abzuschließen.“ • „Das Testen der Software und die damit verbundene Qualitätssicherung kommen dabei oft zu kurz.“ • „eher geringes Interesse für das Testen von Software und der Kontrolle der Entwicklungsarbeit“ in Unternehmen • Aus http://www.pcwelt.de/start/software_os/systemtools/ news/1860669/software_qualitaet_wird_vernachlaessigt/ © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 6
  • 7. Klassifikation von Tests • Klassifikation nach Umfang • Funktional • Korrektheit bezüglich der Spezifikation • Terminierung • Nebenläufige Eingenschaften •Thread-Sicherheit • „Nicht-funktional“ • Performance: Laufzeit und Platz • Load, Stress • Sicherheit • Benutzbarkeit • Interoperabilität • Zuverlässigkeit © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 7
  • 8. Klassifikation von Tests • Klassifikation nach Wissen • Funktion: Black-Box • Struktur: White-Box • Klassifikation nach Struktur • Unit • Einzelne Teile • Integration • Zusammenspiel mehrerer Teile • System • Das gesamte System • User Acceptance Test • Erwartungen der Benutzer © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 8
  • 9. Stetiger Übergang • Unit-, Integration- und Systemtests • Ergänzen sich • Detailierungsgrad und Umfang • Tiefe und Breite • Horizontal und vertikal • Design der Tests • Top-Down • Vom System- über Integrations- zu Unit-Tests • Unit-Tests resultieren als Reproduktionen von Fehlern • Bottom-Up approach • Von Unit-Tests über Integrations- zum System-Test • "a good functional test can be decomposed into a number of unit tests" [BS08] © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 9
  • 10. Korrektheit • Korrektheit • Bezüglich einer Spezifikation • Abgeleitet aus den Anforderungen/Pflichtenheft • Partiell und total (mit Terminierung) • Korrektheitsbeweise • Hoare-Kalkül { P } S { Q } • Zusicherungen •Vorbedingung P •Statements / Anweisungen S •Nachbedingung Q • Wenn P gilt und S ausgeführt wird, muss Q gelten • Invarianten © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 10
  • 11. Korrektheit • Spezifikation ist eine „logische Theorie“ über den Code • Mehr oder weniger formalisiert • Zu zeigen ist • Spezifikation <=> Code • Äquivalenz, nicht Implikation ! • Der Code soll genau und nur die Spezifikation erfüllen • Korrektheitsbeweise sind aufwendig durchzuführen • Wird in Teilbereichen gemacht • Satelliten, Raumfahrt, Medizin • Daher Tests © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 11
  • 12. Traditionelles Testen • Tests traditionell am Ende des Projekts • Analyse, Design, Implementierung, Test • Oft spezielle Testteam (QS/QA) • Nachteile • Späte Rückmeldung • Entwickler müssen sich erst wieder in den Code einarbeiten • Testabdeckung oft nicht ausreichend • Kollateralschäden • Zeitaufwendiges, fehleranfälliges manuelles Testen • Probleme des "ad hoc" Testens • System.out.println(), Debugger • Wissen bleibt im Kopf des Entwicklers © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 12
  • 13. Agiles Testen • Agile Methoden • Agil: flink, beweglich • Extreme Progamming, Scrum • Geringer bürokratischer Aufwand • Wenige Regeln • Berücksichtigung technischer und sozialer Probleme • Einteilung des Projekts in kleinere Schritte • Feature • Eine Säule ist die ... • Testgetriebene Entwicklung • Test driven Development (TDD) • "test first" • „test, code, refactor“ © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 13
  • 14. Testen • Mischformen zwischen Tradition und TDD möglich • „write a little, test a litte, ...“ • Pragmatischer Ansatz • "testing is a choice, not an infectious disease" [BS08] • "testing is a means to an end, and the end is better software" [BS08] • "testing ... is not a golden hammer in a world of nails" [BS08] • „test until fear turns to boredom“ [R05] © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 14
  • 15. Möglichkeiten des Testens • Erfüllung der Anforderungen • Demonstration, das Code funktioniert • Tests auf verschiedenen Plattformen • Regressionstests • Wiedereinführung von bekannten Fehlern • Verhinderung von Kollateralschäden • Abhängigkeiten zwischen den Komponenten • Ermöglicht sicheres Refactoring • Tests bis zur ausführbaren Spezifikation möglich • Automatisierung von Tests • Entwickler haben den Kopf frei für neue Features • Sicherheitsnetz • „peace of mind“ © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 15
  • 16. Automatisierung von Tests • Welche Aufrufarten? • Befehlsgesteuert • Zeitgesteuert • Ereignisgesteuert • „Continuous-Integration“ • Wann ? • Abhängig von der Dauer und den benötigten Ressourcen • Sollten so oft wie möglich laufen • Was wird benötigt ? • Versionsverwaltung • Automatisierte Tests • Rückmeldung • Email, Web-Seiten, RSS-Feeds, Lavalampen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 16
  • 17. Beim Testen zu berücksichtigen • Client • GUI • Rich Client • Web Client • Rich-Client • Business-Logik • Persistenzschicht / Datenanbindung • Server / Service • Middleware / Applikationsserver • Business-Logik • Persistenzschicht / Datenanbindung • Datenbanken • Speicherung und Zugriff © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 17
  • 18. Beim Testen zu berücksichtigen • Programme • Sequentiell • Parallel • Gleiche Aufgaben, mehrere Datenströme • Z. B. Grafikkarten • Nebenläufig / Concurrent • Threads mit unterschiedlichen Aufgaben • Verteilt • Threads auf mehreren Rechnern, SOA • Kommunikation • Synchron • Asynchron • Auf das Ergebnis wird nicht gewartet © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 18
  • 19. JUnit 4 © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 20. JUnit • De facto Standard in der Java Welt • 2001 von Kent Beck und Erich Gamma • Adaption von SUnit aus der Smalltalk Welt (1997) • Versionen 3.8 und 4.5 • 3.8 • Basiert auf Vererbung • JUnit 3.8.2 vom 03.09.2002 • 4.5 • Basiert auf Annotationen •Java 5 • Konzepte von TestNG übernommen • JUnit 4.5 vom 08.08.2008 © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 20
  • 21. JUnit 4: Ein einfaches Beispiel • Funktion, die ihr Argument verdoppelt package example; public class MyMath { /** * Returns i*2. * @param i An integer. * @return Twice the integer. */ public static int mal2(int i) { return i+i; } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 21
  • 22. JUnit 4: Ein einfaches Beispiel • Annotationen • Ausführung der mit @Test annotierten Methoden • Zusicherungen • Erwartete Ergebnisse mit Zusicherungen („assertions“) import org.junit.Test; import static example.MyMath.mal2; import static org.junit.Assert.*; public class MyMathTest { @Test public void mal2Test() { Annotation assertEquals(0, mal2(0)); assertEquals(-2, mal2(-1)); assertEquals(4, mal2(2)); } Zusicherunge } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 22
  • 23. JUnit 4: IDE-Integration • NetBeans 6.1 • Shift-F6 • Eclipse 3.4 • Run As • JUnit-Test © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 23
  • 24. JUnit4: Kommandozeile • Aufruf eines einzelnen Tests auf der Kommandozeile • java -cp CLASSPATH org.junit.runner.JUnitCore KLASSE • Wird selten gemacht • Da JUnit meistens über Ant oder IDE aufgerufen wird © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 24
  • 25. JUnit4: Ant-Integration • Integration in Ant • <junit> und <junitreport> Tasks • Später mehr ... © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 25
  • 26. Ergebnisse von Tests • Error • Während der Ausführung trat ein Fehler auf • Beispiel: Nicht behandelte Exceptions • Failure • Ungültige Zusicherung • Success • Sonst • Warum? • Integration in Java-Exceptions • Unchecked Exceptions • Checked Exceptions •In der Methoden-Signatur spezifiziert © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 26
  • 27. Beispiel für Fehler • Die folgende Klasse produziert Failure und Error public class FailMyMathTest { @Test public void mal2Test() { assertEquals(-1, mal2(-1)); } Failure @Test public void fehler1() { throw new RuntimeException("!"); } Error @Test public void fehler2() throws SQLException { throw new SQLException("!"); } Error } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 27
  • 28. Beispiel für Fehler • NetBeans • Eclipse © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 28
  • 29. Zusicherungen mit assertX • Behauptung / Zusicherung • Das Ergebnis eines Tests liefert bestimmten Wert assertEquals( 0 , MyMath.mal2(0) ); assertEquals( -2 , MyMath.mal2(-1) ); assertEquals( 4 , MyMath.mal2(2) ); Erwartungswert tatsächlicher • Wenn ungleich, wird AssertionFailedError ausgelöst. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 29
  • 30. Zusicherungen mit assertX • Statische Funktionen in der Klasse Assert • Methoden Assert.assert<BEDINGUNG>(). • True: Wahrheit • False: Unwahrheit • Null: Wert gleich Null • NotNull: Wert ungleich Null • Same: Referenz stimmt überein • NotSame: Referenz stimmt nicht überein • Equals: Ruft Object.equals() auf • ArrayEquals: Gleichheit von Arrays • Vorsicht bei Double[] oder Float[] © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 30
  • 31. Zusicherungen mit assertX • Gleitkommaarithmetik ist ungenau • Bei Float und Double ist ein Epsilon-Interval oft notwendig • assertEquals(0.33, 1/3d, 0.01); • Andere Möglichkeit • assertTrue(Math.abs(0.33 - 1/3d) <= 0.01); • Java‘s assert • Java verfügt seit 1.4 über ein assert-Statement • Option -ea beim Start der JVM notwendig • assert booleanExpr; • assert booleanExpr : valueExpr; • Wirft einen AssertionError • Unchecked Exception © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 31
  • 32. Fehlermeldungen • Für alle Assertions: • Optionale Fehlermeldung als erstes Argument • assertEquals(„Fehlermeldung“, 11, 1+2+3+4) © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 32
  • 33. Der Lebenszyklus eines Tests • Standard im xUnit-Bereich • 1. Initialisierung • „Set up“ • Fixture bzw. Kontext • 2. Ausführung des Tests • „Excercise“, „execute“ • 3. Überprüfung • Werden die erwarteten Ergebnisse berechnet? • 4. Herunterfahren • „Tear down“ © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 33
  • 34. Annotationen: Die Basis • @Test • Markiert die Test-Methoden • @Ignore • Ignoriert eine Methode oder Klasse • Auch, wenn diese mit @Test annotiert ist • @Before und @After • Fixture • Ausführung vor und nach jeder Testmethode der Klasse • @BeforeClass und @AfterClass • Fixture • Langlaufende Initialisierungen • Ausführung vor und nach der Testklasse © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 34
  • 35. Annotationen: @Test • @Test markiert die zu testenden Funktionen • Erwartete Exceptions („error“) @Test(expected = IndexOutOfBoundsException.class) public void index() { new ArrayList<String>().get(2); } • Beschränkung der Laufzeit @Test(timeout = 100) public void infinity() { while (true) ; } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 35
  • 36. Annotationen: @Ignore • Ausschluss von Methoden @Ignore("noch nicht fertig") @Test public void something() { ... } • Ausschluss von Klassen @Ignore public class IgnoreMe { @Test public void test1() { ... } @Test public void test2() { ... } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 36
  • 37. Annotationen: @Before und @After • @Before • Ausgeführt vor jeder @Test-Methode • @After • Ausgeführt nach jeder @Test-Methode • @BeforeClass • Ausgeführt nach der Instanzierung der Testklasse • Vor allen @Test-Methoden • Methode muss static sein • @AfterClass • Ausgeführt nach allen @Test- und @After-Methoden • Methode muss static sein • Von allen können beliebig viele angegeben werden © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 37
  • 38. Reihenfolge und Vererbung • Reihenfolge • Initialisierung der Testklasse • @BeforeClass-Methoden (auch die geerbten) • Für alle @Test-Methoden (auch die geerbten) • Instanzierung der Instanz • @Before-Methoden (auch die geerbten) • @Test-Methode • @After-Methoden (auch die geerbten) • @AfterClass-Methoden (auch die geerbten) • Ausführung innerhalb eines Schrittes (rekursiv) • Die Methoden der Oberklasse in beliebiger Reihenfolge • Dann die Methoden der Klasse in beliebiger Reihenfolge © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 38
  • 39. Beispiel: Reihenfolge und Vererbung public class HierarchicalBaseTest { @Before public void beforeBase2() { ... } @Before public void beforeBase1() { ... } @BeforeClass public static void beforeBaseClass2() { ... } @BeforeClass public static void beforeBaseClass1() { ... } @After public void afterBase1() { ... } @After public void afterBase2() { ... } @AfterClass public static void afterBaseClass1() { ... } @AfterClass public static void afterBaseClass2() { ... } @Test public void test1() { ... } @Test public void test2() { ... } public void test3() { ... } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 39
  • 40. Beispiel: Reihenfolge und Vererbung • Ausführung ergibt: Base.BeforeClass 1 Base.BeforeClass 2 Base.Before 1 Base.Before 2 Base.Test 1 Base.After 1 test1 Base.After 2 Base.Before 1 Base.Before 2 Base.Test 2 Base.After 1 test2 Base.After 2 Base.AfterClass 1 Base.AfterClass 2 © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 40
  • 41. Beispiel: Reihenfolge und Vererbung public class HierarchicalTest extends HierarchicalBaseTest { @Before public void before2() { ... } @Before public void before1() { ... } @BeforeClass public static void beforeClass2() { ... } @BeforeClass public static void beforeClass1() { ... } @After public void after1() { ... } @After public void after2() { ... } @AfterClass public static void afterClass1() { ... } @AfterClass public static void afterClass2() { ... } @Test public void test1() { ... } @Test public void test3() { ... } wird super.test3(); } Kein test2() } Ruft Oberklasse © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 41
  • 42. Beispiel: Reihenfolge und Vererbung • Ausführung ergibt:  Fortsetzung Base.BeforeClass 1 After 1 Base.BeforeClass 2 After 2 BeforeClass 1 Base.After 1 BeforeClass 2 Base.After 2 Base.Before 1 Base.Before 1 Base.Before 2 Base.Before 2 Before 1 Before 1 Before 2 Before 2 Test 1 test1 Base.Test 2 test3 After 1 After 1 After 2 After 2 Base.After 1 Base.After 1 Base.After 2 Base.After 2 Base.Before 1 AfterClass 1 Base.Before 2 AfterClass 2 Before 1 test2 Base.AfterClass 1 Before 2 Base.AfterClass 2 Base.Test 3 Test 3 © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 42
  • 43. Organisation von Tests • Zu berücksichtigende Faktoren bei der Organisation • Namenskonventionen • Klassen und Methoden • Verzeichnisse und Pakete • Gruppieren • Laufzeitdauer • Abhängigkeiten • Continuous Integration • Design von Tests • Hierarchie von Testklassen • Gemeinsam genutzer Code • später ... © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 43
  • 44. Namenskonventionen • Klassen • Zu testende Klasse • ClassName • Testklasse • ClassNameTest • Methoden • „Test behaviour, not methods“ [R05] • Verben, statt Substantive! • Nicht wörtlich nehmen, nur ein allgemeiner Ratschlag ! © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 44
  • 45. Verzeichnisse und Pakete • Standard • Zwei Verzeichnisse src und test • Klasse und Testklasse im gleichen Paket • protected-Methoden © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 45
  • 46. Gruppieren von Tests • Unterschiedliche Tests • Unit, Integration, etc. • Laufzeiten • Abhängigkeiten • Datenbank • Applikationsserver • Daher • Gruppieren in TestSuites • Menge von Testklassen • Möglichkeiten • Definition über @SuiteClasses • Aufruf über Ant‘s <junit>-Task © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 46
  • 47. Gruppieren mit @SuiteClasses • Folgende Klasse definiert eine Suite • Zwei Testklassen werden ausgeführt import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) @SuiteClasses({HierarchicalTest.class, PointTest.class}) public class Suite1Test { } • @RunWith erwartet eine Instanz der Klasse Runner • Ein Runner ist eine Klasse zum Ausführen von Tests • @SuiteClasses ist ein Array von Testklassen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 47
  • 48. Gruppieren mit Ant • Der <junit>-Task ruft mit <batchtest> mehrere Tests auf <junit fork="true"> <classpath refid="path.compile" /> <formatter type="brief" usefile="false" /> Ausgabe <formatter type="xml" /> als Text <batchtest todir="build/junit"> und XML <fileset dir="build/classes"> <include name="**/*Test.class" /> TestSuite </fileset> als FileSet </batchtest> </junit> © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 48
  • 49. Ant: Erzeugen von Reports • Für jede Testklasse wird eine XML-Datei erzeugt • Übrigens: Diese Datei ist erweiterbar • Aus diesen kann ein HTML-Report generiert werden <junitreport todir="build/junit-report"> <fileset dir="build/unit"> <include name="TEST-*.xml" /> </fileset> <report format="frames" todir="build/junit-report" /> </junitreport> • Unterschiedliche Stile und Transformationen sind möglich © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 49
  • 50. Ant: Beispiel eines Reports © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 50
  • 51. Continuous Integration • JUnit ist z. B. in Hudson integriert © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 51
  • 52. Beispiel: Exponentielle Glättung • Beispiel: Exponentielle Glättung • public class ExponentialSmoothing { public Double[] smooth(double alpha, Double[] series) { Double[] result = new Double[series.length]; result[0] = series[0]; for (int i = 1; i < series.length; i++) { result[i]= alpha*series[i] + (1-alpha)*result[i-1]; } return result; } } • Fragen: • Korrekt ? Grenzfälle ? © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 52
  • 53. Typische Problemstellungen • Weiterlaufen nach dem ersten Fehler • Stoppen nach dem ersten Fehler • Nur einen Test ausführen • Nur bestimmte Tests ausführen • JUnit in eigener JVM ausführen • Parallele Abarbeitung von Tests • TestListener & TestRunner © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 53
  • 54. Fortgeschrittenes • In JUnit 4.4 gibt es neue, experimentelle Features • Wenig Literatur • Parametrisierte Tests • Data Driven Testing • Theorien • Allgemeine Aussagen • Invarianten • Annahmen • assumeThat() und assumeTrue() • assertThat() und die Hamcrest-Bibliothek • Deklarative Beschreibung von Zusicherungen • „Matcher“ © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 54
  • 55. Parametrisierte Tests • Testfälle sollen möglichst viele Fälle abdecken • Deshalb ist der gleiche Code mit unterschiedlichen Daten auszuführen • Data-Driven-Testing • Runner für parametrisierte Tests • @RunWith(Parameterized.class) • Mit @Parameters annotierte Methode • Definiert eine Collection von Parametern • Die Parameter werden der Testklasse mit dem Konstruktor übergeben. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 55
  • 56. Parametrisierte Tests @RunWith(Parameterized.class) public class ParameterizedMyMathTest { int param; int expected; @Parameters public static Collection data() { Testdaten Collection ps = new ArrayList(); ps.add(new Integer[] {0, 0}); ps.add(new Integer[] {1,2}); ps.add(new Integer[] {-1,-2}); return ps; } public ParameterizedMyMathTest(int a, int b) { this.param = a; this.expected = b; Konstrukt } @Test public void test1() { assertEquals(expected, MyMath.mal2(param)); } Test } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 56
  • 57. Annahmen mit assume • Methoden aus der Klasse Assume • assumeTrue(booleanExpr); • assumeThat • später ... public class AssumeTest { int n = -1; @Test public void t() { System.out.println("Punkt A"); assumeTrue(n >= 0); System.out.println("Punkt B"); }} • Falls die Bedingung nicht zutrifft, wird die Methode verlassen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 57
  • 58. Theorien • Beim JUnit-Testen wird die Funktionalität anhand von Einzelfällen spezifiert. • Keine generellen bzw. allgemeinen Ausssagen! • Beispiel: Die Quadratwurzel @Test public void sqrRootExamples() { assertEquals(2.0, sqrRoot(4)); assertEquals(3.0, sqrRoot(9)); } • Aber: • Die Quadratwurzel hat allgemeine Eigenschaften, die hier nicht getestet werden. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 58
  • 59. Theorien • Folgende Methode ... @Theory public void defnOfSquareRoot(double n) { assumeTrue(n >= 0); assertEquals(n, sqrRoot(n) * sqrRoot(n), 0.01); assertTrue(sqrRoot(n) >= 0); } • ... macht die folgenden Aussagen: • Eine Quadratwurzel ist für nicht-negative Zahlen definiert. • Die inverse Funktion ist die zweite Potenz. • Die Quadratwurzel ist nicht-negativ. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 59
  • 60. Theorien • Die zu testenden Daten werden mit @DataPoint spezifiziert. @DataPoint public static double minusOne = -1.0; public static double four = 4.0; public static double five = 5.0; public static double nine = 9.0; © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 60
  • 61. assumeThat, assertThat und • Deklarative Beschreibung von Annahmen und Zusicherungen • assumeThat([value], [matcher statement]); • assertThat([value], [matcher statement]); • Beispiele • assertThat(x, is(3)); • assertThat(x, is(not(4))); • assertThat(responseString, • either( containsString("color")).or( • containsString("colour"))); • assertThat(myList, hasItem("3")); • Allgemein • anything, describedAs, is • Logisch © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 61
  • 62. assertThat und Hamcrest • Objekte • equalTo, hasToString, instanceOf, isCompatibleType, notNullValue, nullValue, sameInstance • Beans • hasProperty • Collections • array, hasEntry, hasKey, hasValue, hasItem, hasItems, hasItemInArray • Zahlen • closeTo, greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo • Text • equalToIgnoringCase, equalToIgnoringWhiteSpace, containsString, endsWith, startsWith © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 62
  • 63. Trouble-Shooting • junit.jar wird nicht gefunden • CLASSPATH • Bestimmte Tests werden nicht ausgeführt • Finden der Tests im Klassenpfad • Hinzufügen zu Suites • Test verhält sich unerwartet • Einschränkungen von JUnit beachten ! • Jede Testmethode wird in neuer Instanz gestartet • Daher kein Zustand in Testklassen • Reihenfolge unbestimmt © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 63
  • 64. Kompabilität zu JUnit 3 • Ausführung von JUnit-4-Tests mit dem JUnit-3-Runner • Adapter in suite() Methode jeder Klasse public static junit.framework.Test suite() { return new JUnit4TestAdapter(MyMathTest.class); } • Ausführung von JUnit-3-Tests mit JUnit-4-Runner • JUnit 4 ist abwärtskompatibel • Migration von JUnit 3 zu JUnit 4 • Daher meistens nicht notwendig © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 64
  • 65. Nachteile von JUnit 4 • Die Entwickler von TestNG sehen ein paar Nachteile bei JUnit4 [BS08] • Zustandslosigkeit der Testklassen • Kein Zustand in der Testklasse zwischen Testmethoden • Keine Seiteneffekte und Abhängigkeiten • Einerseits gut, manchmal problematisch • Workaround mit statische Variablen ist problematisch • Mehrere Aufrufen bei unterschiedlichen JVMs • Thread-Sicherheit • TestNG bietet weitere Möglichkeiten • Tests überspringen, Gruppierung von Tests • Später ... © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 65
  • 66. JUnit 3 Mein Tip: Nicht mehr verwenden! © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 67. JUnit 3 • JUnit 3 basiert auf Vererbung • Jede Testklasse muss von TestCase erben • ABER: Vererbung ist problematisch • Viele Design-Patterns-Diskussionen • Nur einfache Vererbung in Java • Klassen • TestCase: Für den Testfall • TestSuite: Eine Sammlung an Testfällen. • TestRunner: Zum Ausführen der Tests. • Text basierend • Swing basierend •In 4.4 nicht mehr vorhanden, da IDEs bessere haben. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 67
  • 68. Die Testfunktionen • Superklasse TestCase • Wird abgeleitet und erweitert. public class MyMathTest extends TestCase { public void testMal2() { … } public void testYYY() { … } public void testZZZ() { … } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 68
  • 69. Die abstrakte Klasse TestCase public abstract class TestCase implements Test { private final String fName; public TestCase(String name) { fName = name }; public void run() { setUp(); runTest(); tearDown(); } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 69
  • 70. Nachteile von JUnit 3 • JUnit3 ist „intrusive“, d.h. macht starke Einschränkungen • Jede Testklasse muss von TestCase erben • Nur einfaches Erben in Java • Methoden • Müssen spezielle Namen haben • Wenig flexibel • Umbennen zeitaufwendig, wenn nur eine Methode ausgeführt werden soll, kompilieren notwendig • Haben keine Parameter • Haben keinen Rückgabewert • Testen von Exceptions • Schlecht, da negierte Logik © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 70
  • 71. Nachteile von JUnit 3 • Konfiguration mit setUp und tearDown • nur pro Methode, nicht pro Testklasse • Keine Abhängigkeiten zwischen Tests • Wenn ein Test fehlschlägt, brauchen viele nicht ausgeführt zu werden („skipped tests“) • Erschwert die Ursachenforschung • Testklassen mit Zustand nicht möglich • Workaround mit statischen Variablen ist problematisch • Thread-Sicherheit • Nicht möglich, z. B. • Ausführung nur der fehlerhaften Testklassen • (Geht bei manchen IDEs) © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 71
  • 72. Tests und Design © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 73. Tests und Design • Spannungsfeld zwischen Anwendung und Testklassen • Anwendung • Abhängigkeiten •Frameworks, z. B. GUI, Hibernate, Spring •Applikationsserver und Datenbanken • OO-Prinzipien •Kapselung, „encapsulation“ •Singletons, insb. mit finalen Attributen •Scope •Schlechte Implementierung: Klassen statt Schnittstellen •Verwendung von new statt Factory • Testklassen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 73
  • 74. Tests und Design: Anforderungen • Anforderungen an Tests • Wartbar, einfach verstehbar • Stabil gegenüber • Änderungen am Quellcode, Refaktorisierung • Zukünftigen Anforderungen • Anforderungen an die Anwendung • wie oben • keine festverdrahteten Abhängigkeiten • keine „Sichtbarkeitsprobleme“ für die Testklassen • Oft sind Änderungen für Tests notwendig • „not all code is testable" [BS08] • "constant challenge to write easily testable code" © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 74
  • 75. Tests und Design: Schnittstellen • Schlimmster Fehler • Entwicklung gegen Implementierungen • Nicht gegen Schnittstellen public class BadCode1 { ArrayList<String> list; public BadCode1() { list = new ArrayList<String>(); } } • Stattdessen die allgemeinste Schnittstelle verwenden Collection<String> list; © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 75
  • 76. Tests und Design: Schnittstellen • Zweitschlimmster Fehler • Die konkrete Implementierung im Code festlegen • Hier ist die ArrayList von Außen nicht änderbar • Abhängigkeit • Wenn die Konstruktion sehr lange dauert? • Und nicht getestet werden soll? public class BadCode2 { Collection<String> list; public BadCode2() { list = new ArrayList<String>(); } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 76
  • 77. Tests u. Design: Dependency Injection • 1. Lösungsmöglichkeit • Übergabe im Konstruktor • Entwurfsmuster: Dependency Injection public class BetterCode1 { Collection<String> list; public BetterCode1(Collection<String> list) { this.list = list; } } • Siehe http://martinfowler.com/articles/injection.html © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 77
  • 78. Tests u. Design: Dependency Injection • 2. Lösungsmöglichkeit • Übergabe im Setter • Entwurfsmuster: Dependency Injection public class BetterCode2 { Collection<String> list; public void setList(Collection<String> list) { this.list = list; } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 78
  • 79. Tests und Design: Fabrik / Factory • 3. Lösungsmöglichkeit • Entwurfsmuster: Fabrik / Factory • Übergabe der Fabrik im Konstruktor • Könnte auch in einem Setter übergeben werden public class BetterCode3 { Collection<String> list; public BetterCode3(Factory factory) { list = factory.createCollection(); } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 79
  • 80. Tests und Design: static • Statische Initialisierungen und finale Attribute sind nicht austauschbar. public class BadStaticCode1 { static final String driver = "org.db.driver"; static final String url = "jdbc:db:host/name"; ... static { try { Class.forName(driver); Connection con = DriverManager.getConnection(url, username, password); Statement stmt = con.createStatement(); stmt.executeQuery("SELECT COUNT(*) FROM XYZ"); } catch (ClassNotFoundException e) { ... } • Die Abhängigkeiten sind hier fest verdrahtet © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 80
  • 81. Tests/Design: Singletons und static • Aufgabe: findById() durch Testfunktion zu ersetzen, die nicht auf die Datenbank zugreift. public class BadStaticCode2 { public static Object findById(String id) { // Hole Objekt aus Datenbank ... } public static boolean objectExists(String id) { return (null != findById(id)); } } • Durch Vererbung und Überschreiben nicht möglich ! • Denn: Bei Aufrufen von statischen Methoden wird der Klassenname fest verdrahtet ! • Möglichkeiten: Bytecode manipulieren oder Refaktorisieren © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 81
  • 82. Refaktorisieren • Umgestaltung des bestehenden Quellcodes • Invariante: Semantik / beobachtbares Verhalten • Verbesserung • Lesbarkeit, Übersichtlichkeit, Verständlichkeit • Modularität • Wartbarkeit, Erweiterbarkeit • Entfernung von Redundanzen (DRY, „dont repeat yourself“) • Integriert in die IDEs • Kompliziertere sind manuell durchzuführen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 82
  • 83. Refaktorisieren • Häufige Refaktorisierungen • Umbenennungen • Verschieben • Änderung der Signatur einer Methode • Extraktion einer Methode aus einem Code-Block • Methodenrumpf einfügen und Methode entfernen • Verschieben einer Methode die Klassenhierarchie hinauf oder hinab • Extraktion einer Schnittstelle aus einer Klasse • Generalisierung einer Klasse © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 83
  • 84. Tests und Design • Was tun, damit die Tests erfolgreich sind [B02] ? • Faking it • Erste schnelle Lösung • Die Implementierung imitieren • Methoden geben nur Dummy-Werte zurück • Triangulation • Schrittweise Verkleinerung des Lösungsraums durch Schreiben von Tests • Schrittweise Generalisierung von mehreren Beispielen • Obvious Implementation • Bei kleineren Problemen möglich © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 84
  • 85. Design von Tests: Muster • Allgemeine Richtlinien • Happy path • Failure testing • Java POJOs: Plain Old Java Objects • Stubs, Fakes und Mocks • Data Driven Testing • Nebenläufigkeit / Concurrency • Dependency Injection • Performanz • Im Hinterkopf: • Spezifikation Code • Äquivalenz, nicht Implikation ! © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 85
  • 86. Richtlinie: „Right BICEP“ • Nach [HT03] • Right • Ergebnisse gemäß Spezifikation?, „happy path“ • Boundary condition • Grenzfälle? • Null, leere Strings, negative Werte etc. • Inverse operation • Umkehroperation • Cross check • Gegenprobe mit anderen Mitteln • Error condition • Fehler provozieren • Performance © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 86
  • 87. Richtlinie für Grenzfälle: „CORRECT“ • Nach [HT03] • Conformance • Format, YYYY-MM-DD • Ordering • Range • Wertebereiche, 1..12 für Monat • Reference • Beziehungen zu anderen Klassen • Existence • Leere Daten, null • Cardinality • Time • Reihenfolge, Nebenläufigkeit © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 87
  • 88. Testen von Java POJOs • Am häufigsten zu testen • Methoden equals() und hashcode() • void-Methoden • Konstruktoren • Getter und Setter • Schnittstellen / Interfaces • JavaBeans • Collections • Zusammengesetzte Objekte • „Compound objects“ • Container • Aggregation und Komposition in UML © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 88
  • 89. Java: equals() und hashcode() • Wichtig: equals() wird von assertEquals() benutzt • Für equals() und hashCode() gibt es laut Java-API einen Vertrag • Stichwort „design by contract“ • Diese Methoden werden z. B. von Collections verwendet • equals() muss die folgenden Bedingungen erfüllen • Reflexiv: a ≡ a • Symmetrisch: a ≡ b && b ≡ a • Transitiv: a ≡ b && b ≡ c ==> a ≡ c • Ergibt sich bei Value-Objekten aus den ersten Beiden • Für kein a ist a ≡ null • hashCode() • Falls a ≡ b, dann a.hashCode() ≡ b.hashCode() © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 89
  • 90. Java: equals() und hashcode() • Einfach, aber arbeitsaufwendig • Viele Klassen überschreiben equals() • Einfacher mit EqualsTester von GSBase @Test public void equals() { String a = "Hello"; String b = "Hello"; String c = "Hallo"; new EqualsTester(a, b, c, null); } • Zwei gleiche Elemente a und b • Ein unterschiedliches Element c © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 90
  • 91. Java: void-Methoden • Testen der Seiteneffekte, der Zustandsänderungen • Vorbedingungen • Zustand des Objekts / der Klasse • Aufruf der zu testenden Methode(n) • Nachbedingungen • Zustand des Objekts / der Klasse • Wenn die Seiteneffekte nicht sichtbar sind? • Refaktorisieren • Mit Reflektion • Zugriff auf private Daten und Methoden • JUnitX hat Hilfsmethoden hierfür © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 91
  • 92. Java: Konstruktoren • Kommt selten vor • Henne-und-Ei-Problem: • Ein Objekt ist zum Vergleich notwendig • Ist Zustand sichtbar ? • Testen der Attribute über getter() oder public Attribute • Nicht sichtbar ? • NICHT: Methoden sichtbar (public) machen ! • Die Kapselung nicht brechen! • Möglichkeiten • Neue isValid()-Methode hinzufügen • Erwartungswerte als Parameter übergeben •Der Test wird in der Klasse durchgeführt © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 92
  • 93. Java: Getter und Setter • Nur, wenn diese Logik beinhalten • Validierung • Berechnete Attribute • Meistens „too simple to break“ public class TooSimple { String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getLength() { return name.length(); } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 93
  • 94. Java: Schnittstellen / Interfaces • Schnittstellen definieren nur die Syntax, keine Semantik • Problem: Klassen, die Schnittstelle implementieren, sollen ein bestimmtes Verhalten aufweisen • Beispiel einer Schnittstelle public interface IMailer { public boolean sendMail(String to, String subject, String body); public List<String> getMails(); } • Spezifiziertes Verhalten: • getMails() gibt alle Addressen der bisher gesendeten Mails zurück © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 94
  • 95. Java: Schnittstellen / Interfaces • Lösung: Spezifikation des Verhaltens in abstrakter Testklasse abstract public class AbstractMailerTest { abstract protected IMailer getMailer(); @Test public void sendMail() { int n = getMailer().getMails().size(); getMailer().sendMail("xyz@xyz.xy", "test", "body"); int m = getMailer().getMails().size(); assertEquals(n+1, m); } } • Testklassen der Implementierungen erben sendMail() © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 95
  • 96. Java: Schnittstellen / Interfaces • Testklassen der Implementierungen erben sendMail() • Und müssen nur die getMailer()-Methode implementieren public class MailerImplTest extends AbstractMailerTest { private IMailer mailer; @Override protected IMailer getMailer() { if (null == mailer) { mailer = new MailerImpl(); } return mailer; } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 96
  • 97. Java: JavaBeans • Auszug aus einem Beispiel public class MailBean extends Object implements Serializable { private PropertyChangeSupport propSupport; private String to, subject, body; public MailBean() { propSupport = new PropertyChangeSupport(this); } public void setTo(String value) { String oldValue = to; to = value; Nachricht propSupport.firePropertyChange("to", oldValue, to); } public void addPropertyChangeListener(...) { propertySupport.addPropertyChangeListener(listener); } ... © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 97
  • 98. Java: JavaBeans • JavaBean • Getter und Setter • Nur, wenn sie Logik beinhalten • PropertyChange Events (Event Source) • Eigenen Listener schreiben • Merkt sich den letzten geänderten Wert public class Listener implements PropertyChangeListener { public Object newValue; @Override public void propertyChange(PropertyChangeEvent evt) { newValue = evt.getNewValue(); } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 98
  • 99. Java: JavaBeans • Im Test • Rufen wir einen Setter auf • Und vergleichen mit dem letzen Wert des Listeners @Test public void testFirePropertyChanges() { Listener lst = new Listener(); bean.addPropertyChangeListener(lst); bean.setTo("xyz@xyz.xy"); assertEquals("xyz@xyz.xy", lst.newValue); } • Die Aufrufe von firePropertyChange sind getestet © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 99
  • 100. Java: Collections • Lösung: equals() benutzen • Folgende Bedingungen für die Gleichheit nach equals() • Collection • Gleicher Typ (List, Set, Map) und gleich nach dem Folgenden • List • Gleiche Elemente an gleicher Position • Set • Gleiche Elemente • Map • Gleiche Schlüssel und gleiche Werte für jeden Schlüssel © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 100
  • 101. Java: Komplexe Objekte • Klassen haben evtl. viele Attribute A1,...,An • Zustandsraum • Menge der unterschiedlichen Instanzen einer Klasse • Sei Di ist die Anzahl der Instanzen des Attributs Ai • Größe: D1 * D2 * D3 * ... * Dn • Problem: • Kombinatorische Explosion des Zustandraums • Selbst wenn nur die equals()-Methode getestet werden soll sind n+3 Instanzen mit dem EqualsTester notwendig • 2 Gleiche, n Unterschiedliche und 1 Unterklasse • Im Diasparsoft Toolkit gibt es hier ValueObjectEqualsTest © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 101
  • 102. Java: Komplexe Objekte • Container enthalten andere Objekte und kontrollieren deren Lifecycle • In UML: Aggregation • Problem: • Der Container soll getestet werden • Ohne die anderen Objekte zu instanziieren • Lösung • Refaktorisieren • Dependency-Injection © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 102
  • 103. Stubs, Fakes und Mocks • Beim Film: • Attrappen, Kulissen, Dummys, Doubles, etc. • Beim Testen • Das zum Testen notwendige Minimum herstellen • Wir müssen Schnittstellen und Klassen ersetzen • Schnittstelle • Implementieren • Klasse • Ableiten • Problem: finale Klassen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 103
  • 104. Stubs, Fakes und Mocks • Anwendungsgebiete • Wenn Ausführung zu lange dauert • Datenbanken • Applikationsserver • Simulation von Ereignissen • Festplatte voll • Netzwerk ausgefallen • Wenn Klasse noch nicht implementiert wurde • Bei nichtdeterministischen Ergebnissen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 104
  • 105. Stubs, Fakes und Mocks • Stub • Damit das Programm kompiliert • Ansonsten leer • Fake • Gibt künstliche Daten zurück • Mock • White-Box • Annahmen über Interna der Klasse • "mock objects are not refactoring friendly" • "test brittleness increases with expectations" © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 105
  • 106. Stubs, Fakes und Mocks: Stub • Stub • Damit das Programm kompiliert public class MailerStub implements IMailer { @Override public List<String> getMails() { return null; } @Override public boolean sendMail(String to, String subject, String body) { return false; } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 106
  • 107. Stubs, Fakes und Mocks: Fake • Fake • Gibt künstliche Daten zurück public class MailerFake implements IMailer { @Override public List<String> getMails() { List<String> ls = new ArrayList<String>(); ls.add("xyz@xyz.xy"); return ls; } @Override public boolean sendMail(String to, String subject, String body) { return true; } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 107
  • 108. Stubs, Fakes und Mocks: Mock • Mock • Implementieren die Schnittstelle, API • Und das spezifizierte Verhalten • Methoden werden in der gleichen Reihenfolge aufgerufen •a(), b(), a(), a(), etc. • Die Anzahl der Methodenaufrufe ist gleich • Da Mock-Objekte sehr Nahe am API sind • Sehr abhängig von Änderungen des API • Wenn z. B. eine Refaktorisierung durchgeführt wird • Zerbrechlich, „brittleness“ © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 108
  • 109. Mocks: easyMock • easyMock • Generiert Mock-Objekte • Benötigt Java 5 • Code ist refaktorisierbar • Mock-Generatoren • Funktionieren wie ein Rekorder • Aufzeichnung •Der erwarteten Methodenaufrufe •Der Rückgabewerte • Aufruf des Testcodes • Vergleich der Erwartung mit dem Ist © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 109
  • 110. Mocks: easyMock @Test public void mockTest() { IMailer mock = createMock(IMailer.class); expect(mock.getMails()).andReturn(new ArrayList()); expect(mock.sendMail("xyz@xyz.xy", "Subject", "Body")).andReturn(true); expect(mock.getMails()).andReturn(new ArrayList()); replay(mock); Aufzeichnun mock.getMails(); mock.sendMail("xyz@xyz.xy", "Subject", "Body"); mock.getMails(); verify(mock); } Vergleich © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 110
  • 111. Mocks: jMock • Über jMock liest man selten Gutes • Methodennamen werden als Strings übergeben • Keine Refaktorisierung • Erfordert erben von einer Basisklasse • Anti-Pattern • Intrusive • Verkette Aufrufe von Methoden • Schwierig zu Debuggen • Erwartungen müssen genau angegeben werden • Ist nicht so einfach, wie easyMock • siehe http://www.jmock.org/easymock-comparison.html © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 111
  • 112. Data Driven Testing • Wo können Daten für Tests herkommen? • Java Properties • Umgebungsvariablen • Resource Bundles • Dateien • CSV, XML, etc. • Datenbanken • In JUnit4 mit parametrisierten Testklassen einfach durchzuführen • Das war in JUnit3 nicht so • Beispielklassen, Templates für die obigen Datenquellen in der Fachliteratur [R04] © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 112
  • 113. Nebenläufigkeit / Concurrency • Neue Fragestellungen • Thread-Sicherheit • „thread-safety“ • Datenstruktur bei gleichzeitigem Zugriff korrekt • Verklemmungen • „race-conditions“, „dead-locks“ • Sicherheit • „safety“ • „nothing bad ever happens“ • Lebendigkeit • „liveness“ • „something good eventually happens“ • Fairness © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 113
  • 114. Nebenläufigkeit: Problemstellung • Zustand • Zustand ist die Menge der Attribute / Felder • Methoden ändern den Zustand, Z -> Z‘ • Die Korrektheit einer Java-Klasse • Meistens für sequentiellen Zugriff formuliert • Nicht für gleichzeitigen, parallelen Zugriff • Problem: nicht atomare Methodenaufrufe • count++ • a=b+c • „read-modify-write“ © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 114
  • 115. Nebenläufigkeit: Zustand • Zustandsvariablen und die Schwierigkeit des Testens • „don't share“ • Nur atomarer Zugriff • Konstant, „immutable“ • Unveränderlich • Zum Beispiel String • Veränderlich, Synchronisierung notwendig • volatile • synchronized • Locking protocol •Sperren, locks •Gegenseitiger Ausschluss, „mutual exclusion“ © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 115
  • 116. Nebenläufigkeit: synchronized • Die Variable count ist veränderlich • Es gibt „lost updates“ in inc() public class Unsafe1 { public int count; public void inc() { count++; } synchronized public void inc1() { count++; } public void inc2() { synchronized (this) { count++; }}} • Wichtig: Locks so schnell wie möglich loswerden © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 116
  • 117. Nebenläufigkeit: Atomic • Möglichkeit für einzelne Attribute • Atomare Variablen • in java.util.concurrent.atomic public class Safe1 { public AtomicInteger count; public void inc() { count.addAndGet(1); } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 117
  • 118. Nebenläufigkeit: Thread-Safety • Durch statistische Auswertung • Sprich: Wiederholen des Tests bis der Fehler wahrscheinlich auftritt • Empirisch • Notwendig: • Starten des Tests mit mehreren Threads • Genügend Aufrufe, damit der Fehler auftritt © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 118
  • 119. Nebenläufigkeit: Weitere Punkte • Einfache Lösung: • "Thread confinement" • Beispiele: Swing und Eclipse SWT • Swing und SWT sind nicht thread-sicher • Alles läuft in einem separatem Thread • Verantwortung des Programmierers • Swing Runnable doWorkRunnable = new Runnable() { public void run() { doWork(); } }; SwingUtilities.invokeLater(doWorkRunnable); © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 119
  • 120. Dependency Injection • Frameworks für einfachere Konfiguration • (als die ganzen Setter bzw. Konstruktoren aufzurufen) • Produktivanwendung • Die richtigen Klassen •JDBC, JMS, etc. • Bei Tests • Stubs, Fakes und Mocks • Beispiele • EJB 3.0 • Spring • Seam • Guice © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 120
  • 121. Performanz- und Lasttests • Performancetests • Absolut • Zeitabschätzung mit oberer Schranke • Relativ • Messen der Zeit für n=10, dann für n=100 • Abschätzung nach O(n)-Notation + konstanter Faktor • Lange Laufzeiten • Daher von den Unit-Tests separieren • Frameworks • JUnitPerf • JMeter • The Grinder © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 121
  • 122. Performanz: Absolut • Absolut • Zeitabschätzung mit oberer Schranke @Test(timeout = 1000) public void absolute() { run(100); } • Nachteile • Abhängig von Hardware • Abhängig von Auslastung © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 122
  • 123. Performanz: Relativ • Relativ • Messen der Zeit für n=k, k=10000 • Dann für n=k*10 • Abschätzung nach O(n)-Notation + konstanter Faktor @Test public void relative() { Date d1 = new Date(); run(10000); Date d2 = new Date(); run(100000); Date d3 = new Date(); long ms1 = d2.getTime() - d1.getTime(); long ms2 = d3.getTime() - d2.getTime(); Zeit assertTrue("Performance", ms1000 < ms100 * 10); } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 123
  • 124. JUnitPerf • Erweiterung von TestCase • Daher JUnit 3.8 • Dekorator-Pattern • erlaubt die Erweiterung bestehender Tests • unabhängig von bestehenden Tests • TimedTest • misst die vergangene Zeit • maximale Zeit kann angegeben werden Test case = new MyTest("testMethod"); Test timedTest = new TimedTest(case, 1000); © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 124
  • 125. JUnitPerf • LoadTest • simuliert mehrere User und Iterationen • Beispiel • Für 10 Benutzer und 100 Iterationen • Alle 100 ms ein neue Benutzer Timer timer = new ConstantTimer(100); Test case = new MyTest("testMethod"); Test loadTest = new LoadTest(case, 10, 100, timer); • Die gemessene Zeit ist • setUp() + Testmethode + tearDown() • Kein fully fledged Performance profiling tool © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 125
  • 126. JMeter • Lade und Performanztests für Server • Web, HTTP, HTTPS • SOAP • Datenbanken / JDBC • LDAP • JMS • POP3 (Email) • Ausführung von Testplänen • Aufzeichnung von Testschritten • GUI-Oberfläche • Keine JUnit-Erweiterung ! © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 126
  • 127. The Grinder • Verteilte Test-Framework • Load-Tests • Anpassbar an alle Java APIs • HTTP, SOAP, REST, CORBA, RMI, EJBs, JMS • Für Entwickler • Aktuelle Version • The Grinder 3 • Tests werden in Jython spezifiziert • Java-Implementierung von Python • Test von Web- oder EJB-Anwendungen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 127
  • 128. Äquivalenz, nicht Implikation • Beispiel: Binäre Suche in einem Array • Nach • Oram, Wilson. „Beautiful Code“, O'Reilly 2007. Kapitel 7 • Gegeben sei ein Array arr von Integern und ein Integer i • Gesucht • Die Position von i, falls i enthalten ist • -1, sonst • Laufzeitanforderung O(lg n) • Die erste Version der binären Suche ist von 1946, die erste Fehlerfreie von 1958. • Der Korrektheitsbeweis in John Bentley‘s „Programming Pearls“ macht die Annahme der exakten Arithmetik. • Daher ist ein Bug bei großen Arrays enthalten. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 128
  • 129. Äquivalenz, nicht Implikation • Die Theorie über die binäre Suche search(arr, i) • Annahmen „hin“ • search(arr, i) = -1 => arr enthält i nicht • search(arr, i) = k & k>-1 => arr enthält i an Position k • Annahmen „her“ • arr enthält i nicht => search(arr, i) = -1 • arr enthält i an Position k => search(arr, i) = k & k>-1 • Performanz • arr.length = n => #{search(arr, i)} <= 1 + log2 n • wobei #{} die Anzahl der Arbeitsschritte ist © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 129
  • 130. Erweiterungen von JUnit © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 131. JUnit 3 und JUnit 4 • Erweiterungen • Die auf JUnit 3 aufsetzen und von TestCase erben • Können nicht immer in JUnit 4 Klasse benutzt werden • Möglichkeit: • JUnit 3 Klasse schreiben • Und mit JUnit 4 Runner (mit den anderen Tests) aufrufen • Eventuell gibt es Adapter oder Workarounds • Im WWW danach suchen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 131
  • 132. Nützliche Zusatzprogramme © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 133. PMD • PMD ist ein Werkzeug zur Quellcodeanalyse. • Es kann mögliche Fehler, suboptimalen Code, etc. finden • Ist mit Regeln konfigurierbar und erweiterbar © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 133
  • 134. Findbugs • Findbugs analysiert die Qualität des Quellcodes. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 134
  • 135. Checkstyle • Checkstyle analysiert die Code-Qualität. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 135
  • 136. JavaNCSS • JavaNCSS berechnet die Anzahl der reinen Codezeilen. • Non-commenting source statements © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 136
  • 137. Testabdeckung © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 138. Testabdeckung: Grundlagen • „Überdeckungstest“ • Metrik der Code-Qualität • Welche Teile des Codes werden beim Test ausgeführt ? • Granularitäten • Klasse • Methode • Statement • Block • Branch/Decision • Schwierigkeit • kombinatorische Explosion © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 138
  • 139. Testabdeckung: Warnung • Die Testabdeckung ... • Sollten NIE als Metrik über die Qualität der Tests oder des Codes verstanden werden • Ist nur ein Indikator für Problembereiche • Kann also nur negative Aussagen machen, keine positiven • „designing for coverage is evil“ [BS08] • Einfache Tests, die immer nur das „richtige“ testen, ergeben auch 100% Abdeckung • „coverage exclusion comments“ sind strikt zu vermeiden © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 139
  • 140. Testabdeckung: Werkzeuge • Beispiele • Kommerziell • Atlassian Clover •Ab 1200 $ für Einzelplatzlizenz, $2200 für 10 Benutzer • JCoverage (Eclipse-Plugin, 3.1 und 3.2) •19.95 GBP pro Entwickler pro Jahr • Open Source • Cobertura • EMMA © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 140
  • 141. Testabdeckung: Arbeitsweise • Arbeiten durch Modifizierung des Codes • Methoden zur Sammlung von statistischen Daten werden vor jede Anweisung eingefügt • „Instrumentalisieren“ • Möglichkeiten der Code-Änderungen • Quellcode • Bytecode • Oder der Java VM © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 141
  • 142. Testabdeckung: Cobertura • Ändert den Bytecode © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 142
  • 143. Testabdeckung: Cobertura • Die Methode createIgnoreBranches wurde nicht getestet © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 143
  • 144. Testabdeckung: NetBeans • Code Coverage Plugin • Benutzt EMMA, ab Java 6 © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 144
  • 145. Testabdeckung: NetBeans © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 145
  • 146. DbUnit © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 147. DbUnit • DbUnit ist ein Testwerkzeug für die Datenbank. • Testdaten werden in XML-Dateien definiert. • Damit werden sowohl Fixtures als auch erwartete Ergebnisse spezifiziert • Erweitert TestCase, daher JUnit 3 • Das Datenbank-Schema wird in einer DTD gespeichert <!ELEMENT PREDICTION_GROUP_TYPE EMPTY> <!ATTLIST PREDICTION_GROUP_TYPE ID CDATA #REQUIRED NAME CDATA #IMPLIED > © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 147
  • 148. DbUnit • Inhalte von Tabellen werden in XML gespeichert <PREDICTION_GROUP_TYPE ID="1" NAME="Prognosegruppe" /> <PREDICTION_GROUP_TYPE ID="2" NAME="Trendgruppe" /> • DbUnit verfügt über Zusicherungen public static void assertEquals(ITable expected, ITable actual) public static void assertEquals(IDataSet expected, IDataSet actual) © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 148
  • 149. Allgemeines zum Testen von DB • Testen auf einer „großen“ Datenbank hat Nachteile: • Die Performanz ist schlecht. • Die Entwickler stören sich evtl. gegenseitig • Jedem Entwickler sein eigenes Schema • Lösung: In-Memory Datenbank • HSQLDB • Derby. • Die In-Memory DB wird einmal initialisiert und kann schnell für jeden Testfall „frisch“ gemacht werden und schnell die Testfälle abarbeiten. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 149
  • 150. XMLUnit © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 151. XMLUnit • XML-Dokumente sind überall • Zu Testen sind ... • Konformität, Validierung • Document Type Definition DTD • XML Schema Definition (XSD) • Reihenfolge der Elemente • Transformationen mit XSLT • Rudimentäre Lösung • Vergleich der Elemente mit XPath • XMLUnit • Komfortabler © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 151
  • 152. Erinnerung: XML • XML • Elemente („tags“) und Attribute • Starttags und Endtags, verkürzter Endtag ‚/>‘ • Hierarchie mit Baumstruktur • DOM „document object model“ • <project name="Tutorial" default="build"> <target name="build"> <echo message="Hallo Welt!" /> <echo message="Hallo nochmal!" /> </target> </project> Elemente Attribute © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 152
  • 153. Erinnerung: XML-Baumstruktur • <project name="Tutorial" default="build"> <target name="build"> <echo message="Hallo Welt!" /> <echo message="Hallo, nochmal!" /> </target> </project> project name=“Tutori al“ target echo echo message=“Hallo, Welt“ message=“Hallo, © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 153
  • 154. XMLUnit: Möglichkeiten • XMLUnit kann • Unterschiede zwischen Dokumenten • Diff und DetailedDiff • Gültigkeit („validity“) eines Dokuments • Validator • Ergebnis einer XML-Transformation mit XSLT • Transform • Ergebnisse von XPath-Ausdrücken • XpathEngine • Knoten durch DOM-Traversal ermitteln • NodeTest © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 154
  • 155. XMLUnit: Möglichkeiten • XMLUnit unterscheidet beim Vergleich • identisch („identical“) • similiar • „recoverable“ • auch selbst definierbar durch DifferenceListener • different • „unrecoverable“ © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 155
  • 156. XMLUnit • Unterschiede werden in Diff-Objekten gespeichert. @BeforeClass public static void setUp() { XMLUnit.setIgnoreWhitespace(true); } @Test public void textsAreIdentical() throws SAXException, IOException { Diff diff = new Diff(XmlProducer.getXml1(), XmlProducer.getXml2()); assertTrue(diff.toString(), diff.identical()); } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 156
  • 157. Rich Clients © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 158. Rich Clients-Frameworks für Java • Viele Frameworks • Swing und Abstract Windowing Toolkit (AWT) • Eclipse Standard Windowing Toolkit (SWT) • Eclipse Rich Client Platform (RCP) • Basiert auf SWT • NetBeans • Zukünftige Entwicklungen • Swing Application Framework (JSR 296) • JavaFX • Spring richclient © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 158
  • 159. Rich Clients-Frameworks für Java • Aspekte eines GUI-Frameworks • Kleinere Aufgaben und Utilities • Validierung von Benutzereingaben • Formatierung von Ausgaben • Layout und Anzeige der graphischen Elemente • Die eigentliche Hauptaufgabe der GUI • Tip: Nur automatisiert testen, wenn unbedingt nötig •Beispiel: Bibliothek von Widgets • Interaktion mit dem Benutzer • Ereignisse, Events • Zustand und zustandsbasierte Änderungen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 159
  • 160. Testen von Rich Clients • Schwierig zu Testen • Abhängigkeit von GUI-Klassen • GUI reagiert nur auf Ereignisse • Die GUI-Elemente sind für die Tests nicht ohne weiteres sichtbar • Manche Tools blockieren den Rechner • Struktur der Oberfläche ändert sich während der Entwicklung oft • Einfachste Lösung • GUI nur zur Darstellung • Den Code in der GUI auf ein Minimum reduzieren • Keine Logik in die GUI © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 160
  • 161. MVC und Präsentationsmodell • Entwurfsmuster „Model-View-Controller“ • Model: Datenmodell • View: Darstellung (GUI) • Controller: Logik / Steuerung View Controller Model • Es gibt viele kleinere Variationen • Leichte Unterschiede zwischen Web- und Rich-Clients © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 161
  • 162. MVC • Bei Swing • View und Controller vereint bzw. eng-gekoppelt • Verursacht beim Testen Schwierigkeiten • Controller kann nicht separat getestet werden View Controller Model • Trennung © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 162
  • 163. Neuere Lösung: Presentation-Model • Presentation Model • Kein Zustand im GUI • Da schwierig in Tests an den Zustand heranzukommen ist • Enthält die Daten und Logik der Oberfläche • Data Binding zwischen GUI und Präsentationsmodell • http://martinfowler.com/eaaDev/PresentationModel.html • Ähnlich • Model-View-Presenter • Supervising Controller • Passive View oder „The Humble Dialog Box“ © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 163
  • 164. Data Binding • Für jedes GUI-Element, das vom Benutzer geändert werden kann gibt es ein Modell-Element • Problem • Synchronisierung zwischen beiden • Validierung von Eingaben • Data Binding Frameworks • Eclipse Data Binding (vorher JFace Data Binding) • JGoodies • Beans Binding (JSR 295) • Das Präsentationsmodell kann mit JUnit getestet werden • Ist noch ein relativ neues Thema. • Noch nicht in voller Breite unterstützt © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 164
  • 165. Testen von GUIs • Testing-Frameworks müssen die folgenden Aufgaben unterstützen • Finden von Komponenten in der Hierarchie • Absolute und relative Angaben •Finde den Knopf mit dem Namen „Ok“ •Finde die dritte Zeile in einer Tabelle • Programmatisch die GUI manipulieren • Buttons klicken • Elemente auswählen • E-i-n-g-a-b-e-n machen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 165
  • 166. Testen von GUIs • Viele Frameworks und Tools • Siehe http://www.testingfaqs.org/t-gui.html • Open Source • java.awt.robot • Abbot (Swing, AWT, SWT, TestNG) • Jemmy • Wird auch vom NetBeans-Team genutzt • JFCUnit • Pounder • UiSpec4J • GSBase © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 166
  • 167. Beispielanwendung • Der Celsius-zu-Fahrenheit-Umwandler aus dem Java- Web-Tutorial • Swing-Komponenten • JFrame • JTextField • Eingabe • JLabel • Celsius • JButton • Zum Konvertieren • JLabel • Ausgabe des Ergebnisses © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 167
  • 168. Jemmy • Im Rahmen von NetBeans entstanden • API für den Zugriff auf die Interna von Swing • Hängt sich in die Ereignisverarbeitung von Swing ein • Ortet Komponenten anhand der Events • Operatoren • Zugriff auf die Swing-Elemente • Typisches Vorgehen beim Testen • Man erstellt einen JFrame • Addiert die zu testenden Komponente • Initialisiert den Zustand • Änderung des Zustands • Kontrolle des Ergebnisses © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 168
  • 169. Jemmy: Beispiel • Test des Celsius-zu-Fahrenheit-Umwandlers public class Jemmy1Test { JFrame frame; JFrameOperator frameOp; @Before public void setUp() { frame = new CelsiusConverterGUI(); frame.setVisible(true); frameOp = new JFrameOperator(frame); } @After public void tearDown() { frame.dispose(); frameOp.dispose(); } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 169
  • 170. Jemmy: Beispiel • Die Test-Methode • Suchen der Elemente und Eingabe machen • Knopf drücken • Ergebnis vergleichen @Test public void runApplication() { JTextField textField = JTextFieldOperator.findJTextField(frame, chooser); textField.setText("1234"); JButton button = JButtonOperator.findJButton(frame, chooser); button.doClick(); JLabel label = JLabelOperator.findJLabel(frame, chooser, 1); assertEquals("2253 Fahrenheit", label.getText()); } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 170
  • 171. Jemmy: Beispiel • Zum Suchen von Elementen in der Hierarchie der GUI werden ComponentChooser verwendet • Der einfachste gibt das erste Element zurück @Test ComponentChooser chooser = new ComponentChooser() { public boolean checkComponent(Component arg0) { return true; } public String getDescription() { return ""; } }; © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 171
  • 172. Web-Anwendungen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 173. Testen von Web-Anwendungen • Arten • Statische Webseiten • Dynamische Webseiten • JSP, Velocity • Frameworks • Struts, JSF, Grails • Auch Web-Anwendungen benutzen MVC • Geschäftslogik sollte in POJOs implementiert sein • Kann damit unabhängig getestet werden © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 173
  • 174. Testen von Web-Anwendungen • Client • Browser • „Makro-Rekorder“ •Aufzeichnen von Benutzerinteraktionen •Wiederabspielen • Browser-Emulatoren • Simulieren Web-Browser • Machen Zustand zum Testen zugänglich • Server • Im Container/Server • Leichtgewichtige bzw. simulierte Container © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 174
  • 175. Testen von Web-Anwendungen • Viele Frameworks und Tools • http://java-source.net/open-source/web-testing-tools • Frameworks • Selenium • HttpUnit • HtmlUnit • Canoo Web Test • Apache Shale • StrutsTestCase (veraltet, nur Struts 1.2 und 1.3) • JSFUnit © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 175
  • 176. Beispielanwendung • Das „Hallo-Welt“ der Webanwendungen Start Eingabe Ausgabe © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 176
  • 177. Beispielanwendung • Datei index.jsp <%@page contentType="text/html" ageEncoding="UTF-8"%> <html> <body> <form action="show.jsp" id="eingabe"> Form <input type="text" name="eingabefeld" size="24"> <input type="submit" name="senden"> </form> </body> </html> • Stellt eine Eingabefeld dar © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 177
  • 178. Beispielanwendung • Datei show.jsp <%@page contentType="text/html" pageEncoding="UTF-8"%> <html> <body> id <p> Die Eingabe war: <div id="ausgabe">'<%= request.getParameter("eingabefeld")%>'</ div> </p> JSP </body> </html> • Bei Aufruf von http://localhost:8080/WebApp1/show.jsp?eingabefeld=Hallo • wird „Hallo“ ausgegeben © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 178
  • 179. HttpUnit testet Web-Applikationen • HttpUnit simuliert einen Web-Client • Kann Requests senden und Responses empfangen • Unterstützt verschiedene Authentisierungen • Unterstützt Cookies • Werden oft zur Speicherung von Zuständen benutzt • JavaScript • Unterstützt Weiterleitung von Seiten • Wird von Frameworks, wie z. B. Struts verwendet • Der Status eines Web-Clients kann ermittelt und ausgewertet werden. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 179
  • 180. HttpUnit • HttpUnit unterstützt u. a. die folgenden Klassen • WebConversation • Eine Web-Verbindung • WebRequest • GET oder POST zu einer URL • WebResponse • Die Antwort des HTML-Servers • WebForm • Eine HTML-Form • HTMLElement • Ein HTML-Element, z. B. <p>Beispiel</p> • Funktionen zum Suchen von Elementen usw. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 180
  • 181. HttpUnit: JUnit4 • Wir überprüfen dieses mit einem Test. public class HttpUnitTest { final private String text = "Hallo Welt!"; @Test public void test1() throws IOException, SAXException { WebConversation conv = new WebConversation(); String url = "http://localhost:9080/WebApp1/index.jsp"; WebRequest req = new GetMethodWebRequest(url); WebResponse res = conv.getResponse(req); 1. Seite WebForm form = res.getFormWithID("eingabe"); req = form.getRequest(); req.setParameter("eingabefeld", text); Ausfüllen res = conv.getResponse(req); HTMLElement elem = res.getElementWithID("ausgabe"); assertEquals("'" + text + "'", elem.getText()); }} 2. Seite © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 181
  • 182. Selenium IDE • Makro-Rekorder • Browser-Erweiterung © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 182
  • 183. Selenium IDE • Die aufgezeichneten Tests lassen sich als JUnit3-Test exportieren. public class SeleniumTest extends SeleneseTestCase { public void setUp() throws Exception { setUp("http://localhost:9080/examples/jsp/", "*chrome"); } public void testNew() throws Exception { selenium.open("http://localhost:9080/examples/jsp/"); selenium.click("//tr[6]/td[2]/a[2]"); selenium.waitForPageToLoad("30000"); ... selenium.click("submit"); selenium.waitForPageToLoad("30000"); verifyTrue(selenium.isTextPresent("oranges")); verifyTrue(selenium.isTextPresent("apples"));}} © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 183
  • 184. JEE / J2EE © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 185. JEE / J2EE • Frage: Im Server oder Stand-alone • Problem: Abhängigkeiten • POJOs sind einfach zu testen • Integrationstests benötigen den Server • Sicherheit, Transaktionen, etc. • Generell: • Bei EJB3 und Spring einfacher als bei EJB2 • Frameworks (Auszug) • Apache Cactus • JUnitEE • EJB3Unit • ORMUnit © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 185
  • 186. Apache Cactus • Generelles Framework • Serverseitiger Code • Servlets, EJBs, Tag-Bibliotheken • Schwerpunkt Integrationstests • Erweiterung von JUnit3 • ServletTestCase • JspTestCase • FilterTestCase • ServletTestSuite © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 186
  • 187. JUnitEE • JUnitEE ermöglicht Unit-Tests auf dem Applikationsserver. • Es wird ein EAR/WAR/JAR erstellt, das JUnitEE und die JUnit-Tests enthält • Dieses wird auf dem Server deployed • Tests sind per RMI oder über eine Webseite aufrufbar © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 187
  • 188. TestNG © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 189. TestNG • Aus Unzufriedenheit mit JUnit3 entwickelt [BS08] • Diente als Vorbild für Neuerungen in JUnit4 • Basiert auf Annotationen • Java 5 • Java 4 mit JavaDoc-Annotationen möglich • Ziel • Unit-, Integrations- und System-Tests • Flexible Konfiguration von Tests • Gruppierungen • Tests überspringen • Tests auf anderen Maschinen ausführen • Parallele Ausführung von Tests © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 189
  • 190. TestNG: Die Annotationen • Annotieren der Methoden wie bei JUnit 4 mit • @Test • Flexibler als bei JUnit4 • Abhängigkeit von Gruppen (dependsOnGroups, groups) • Abhängigkeit von Methoden (dependsOnMethods) • Mehrmalige Aufrufe in mehreren Threads • invocationCount, threadPoolSize • successPercentage • Parametrisierte Tests / Data-Driven Tests • dataProvider, dataProviderClass • Testmethoden dürfen Argumente und Rückgabewerte haben © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 190
  • 191. TestNG: Die Annotationen • Before- und After-Annotationen • @BeforeSuite, @AfterSuite • Testsuite • @BeforeGroups, @AfterGroups • Gruppe • @BeforeClass, @AfterClass • Klasse (wie bei JUnit 4) • @BeforeTest, @AfterTest • Test • @BeforeMethode, @AfterMethod • Vor jeder Methode (wie bei JUnit 4 @Before und @After) © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 191
  • 192. TestNG: Die Annotationen • @DataProvider • Erzeugt Daten für eine Test-Methode • @Factory • Methode, die Tests erzeugt • @Parameters • Beschreibt die Parameter der Testmethode • Testmethoden dürfen Parameter haben © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 192
  • 193. Akzeptanztests © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 194. Akzeptanztests • Erweiterung des TDD auf Akzeptanztests [K07] • Acceptance TDD • User Story als Spezifikation • Wer macht was wann und warum • „power of storytelling“ • Kunde kann in eigener Sprache formulieren • Deklarativ, nicht operationell • Akzeptanztests werden mit dem Kunden geschrieben • HTML, Excel, Word-Dokumente • Anforderungen in tabellarischer Form © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 194
  • 195. Fit - Framework for Integrated Test • Spezifikation in HTML-Dateien • Vorteil: Fachabteilung, „executable specification“ • Java-Klasse fit.CalculateCredit ist Fixture • Attribute: months, reliable, balance • Methoden: allowCredit(), creditLimit() © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 195
  • 196. Fit: Fixture public class CalculateCredit extends fit.ColumnFixture { public int months; public boolean reliable; public double balance; private Credit credit = new Credit(); public boolean allowCredit() { return credit.allowsCredit(months, reliable,balance); } public double creditLimit() { return credit.limit(months,reliable,balance); } } © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 196
  • 197. Fit: Ergebnis • Ergebnis © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 197
  • 198. Fit: Weiteres • Fixtures • ColumnFixture • Abbildung von Spalten der Testdaten zu Attributen der Testklassen • Eine pro spezifizierter Tabelle • RowFixture • Flexible und anpassbare Interpretation von Zeilen aus der Datenbank • ActionFixture • Interpretiert Zeilen der Datenbank als Kommandos © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 198
  • 199. FitNesse • Front-End für Fit • Kollaborative Software-Entwicklung • Acceptance Testing Framework • Wiki • Web Server • Benutzt Fit © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 199
  • 200. Referenzen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
  • 201. Bücher über JUnit 3 • [MH03] • Vincent Massol, Ted Husted. JUnit in Action. Manning. 2003. • [R04] • J. B. Rainsberger. JUnit Recipes. Manning. 2004. • [HT03] • Andy Hunt, Dave Thomas. Pragmatic Unit Testing. Pragmatic Programmers, LCC. 2003. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 201
  • 202. Bücher über TDD • [B02] • Kent Beck. Test-Driven Development. By Example. Addison-Wesley. 2002. • [K07] • Lasse Koskela. Test Driven. Practical TDD and Acceptance TDD for Java Developers. Manning. 2007. • [M07] • Gerard Meszaros. xUnit Test Patterns: Refactoring Test Code. Addison-Wesley. 2007. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 202
  • 203. Bücher über JEE • [BS08] • Cedriv Beust, Hani Suleiman. Next Generation Java Testing: TestNG and Advanced Concepts. Addison-Wesley. 2008. • [R06] • Chris Richardson. POJOs in Action. Manning. 2006 • [F04] • Michael Feathers. Working Effectively with Legacy Code. Prentice Hall. 2004. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 203
  • 204. Webseiten Hauptseite http://junit.org/ JUnit FAQ http://junit.sourceforge.net/doc/faq/faq.htm JCoverage http://www.jcoverage.com/ Code Coverage Für NetBeans http://codecoverage.netbeans.org/ Testabdeckung EMMA http://emma.sourceforge.net/ Cobertura http://cobertura.sourceforge.net/ JUnitPerf http://www.clarkware.com/software/JUnitPerf.html Performance JMeter http://jakarta.apache.org/jmeter/index.html The Grinder http://grinder.sourceforge.net/ Fit http://fit.c2.com/ Akzeptanztests FitNesse http://www.fitnesse.org/ Selenium http://selenium.openqa.org/ HttpUnit http://httpunit.sourceforge.net/ Web Apache Shale http://shale.apache.org/shale-test/index.html HTMLUnit http://htmlunit.sourceforge.net/ Jemmy Module Für NetBeans http://jemmy.netbeans.org/ GUI Abbot http://abbot.sourceforge.net/doc/overview.shtml Jakarta Cactus http://jakarta.apache.org/cactus/ JEE JUnitEE http://www.junitee.org/ Jester http://jester.sourceforge.net/ Mutation Testing Jumble http://jumble.sourceforge.net/ jMock http://www.jmock.org/ Mocks EasyMock http://www.easymock.org/ GSBase http://gsbase.sourceforge.net/ Hamcrest http://code.google.com/p/hamcrest/ JUnitX http://www.extreme-java.de/junitx/ Sonstige JUnit-Addons http://sourceforge.net/projects/junit-addons DbUnit http://www.dbunit.org/ XMLUnit http://xmlunit.sourceforge.net/ © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 204