Schulung
„Testgetriebene Entwicklung
        mit JUnit 4“
       © 2008 - 2009 Jörn Dinkla

           joern@dinkla.com
  ...
Vorstellung
•   Dipl.-Inform. Jörn Dinkla
•   Schwerpunkte
     • Java Entwicklung (J2SE, JEE)
     • Moderne Programmiers...
Überblick



© 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
Überblick: JUnit und Testwerkzeuge
•   Grundlagen des Testen
•   JUnit
•   Tests und Design
     • Standards
     • Nebenl...
Grundlagen des Testens



       © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
Software-Qualität wird vernachlässigt
•   Aus der PC Welt vom April 2008
     • „Software-Hersteller haben häufig nur ein ...
Klassifikation von Tests
•   Klassifikation nach Umfang
     • Funktional
           • Korrektheit bezüglich der Spezifikat...
Klassifikation von Tests
•   Klassifikation nach Wissen
     • Funktion: Black-Box
     • Struktur: White-Box
•   Klassifik...
Stetiger Übergang
•   Unit-, Integration- und Systemtests
     • Ergänzen sich
     • Detailierungsgrad und Umfang
       ...
Korrektheit
•   Korrektheit
     • Bezüglich einer Spezifikation
          • Abgeleitet aus den Anforderungen/Pflichtenhef...
Korrektheit
•   Spezifikation ist eine „logische Theorie“ über den Code
     • Mehr oder weniger formalisiert

•   Zu zeig...
Traditionelles Testen
•   Tests traditionell am Ende des Projekts
     • Analyse, Design, Implementierung, Test
     • Oft...
Agiles Testen
•   Agile Methoden
     • Agil: flink, beweglich
     • Extreme Progamming, Scrum
     • Geringer bürokratis...
Testen
•   Mischformen zwischen Tradition und TDD möglich
     • „write a little, test a litte, ...“

•   Pragmatischer An...
Möglichkeiten des Testens
•   Erfüllung der Anforderungen
•   Demonstration, das Code funktioniert
•   Tests auf verschied...
Automatisierung von Tests
•   Welche Aufrufarten?
     • Befehlsgesteuert
     • Zeitgesteuert
     • Ereignisgesteuert
  ...
Beim Testen zu berücksichtigen
•   Client
     • GUI
           • Rich Client
           • Web Client
     •   Rich-Client...
Beim Testen zu berücksichtigen
•   Programme
     • Sequentiell
     • Parallel
            • Gleiche Aufgaben, mehrere Da...
JUnit 4



© 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
JUnit
•   De facto Standard in der Java Welt
•   2001 von Kent Beck und Erich Gamma
•   Adaption von SUnit aus der Smallta...
JUnit 4: Ein einfaches Beispiel
•       Funktion, die ihr Argument verdoppelt

        package example;
        public cla...
JUnit 4: Ein einfaches Beispiel
•   Annotationen
     • Ausführung der mit @Test annotierten Methoden
•   Zusicherungen
  ...
JUnit 4: IDE-Integration
•   NetBeans 6.1
     • Shift-F6




•   Eclipse 3.4
     • Run As
         • JUnit-Test




    ...
JUnit4: Kommandozeile
•   Aufruf eines einzelnen Tests auf der Kommandozeile
     •   java -cp CLASSPATH org.junit.runner....
JUnit4: Ant-Integration
•   Integration in Ant
      • <junit> und <junitreport> Tasks
•   Später mehr ...




           ...
Ergebnisse von Tests
•   Error
     • Während der Ausführung trat ein Fehler auf
     • Beispiel: Nicht behandelte Excepti...
Beispiel für Fehler
•   Die folgende Klasse produziert Failure und Error

public class FailMyMathTest {

  @Test

  public...
Beispiel für Fehler
•   NetBeans




•   Eclipse




               © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com   28
Zusicherungen mit assertX
• Behauptung / Zusicherung
   • Das Ergebnis eines Tests liefert bestimmten Wert


     assertEq...
Zusicherungen mit assertX
•   Statische Funktionen in der Klasse Assert
•   Methoden Assert.assert<BEDINGUNG>().
     • Tr...
Zusicherungen mit assertX
• Gleitkommaarithmetik ist ungenau
• Bei Float und Double ist ein Epsilon-Interval oft notwendig...
Fehlermeldungen
•   Für alle Assertions:
     • Optionale Fehlermeldung als erstes Argument
     • assertEquals(„Fehlermel...
Der Lebenszyklus eines Tests
•   Standard im xUnit-Bereich

•   1. Initialisierung
     • „Set up“
     • Fixture bzw. Kon...
Annotationen: Die Basis
•   @Test
     • Markiert die Test-Methoden
•   @Ignore
     • Ignoriert eine Methode oder Klasse
...
Annotationen: @Test
•   @Test markiert die zu testenden Funktionen

•   Erwartete Exceptions („error“)
	   @Test(expected ...
Annotationen: @Ignore
•   Ausschluss von Methoden
	   @Ignore("noch nicht fertig")

   @Test

   public void something() {...
Annotationen: @Before und @After
•   @Before
     • Ausgeführt vor jeder @Test-Methode
•   @After
     • Ausgeführt nach j...
Reihenfolge und Vererbung
•   Reihenfolge
     • Initialisierung der Testklasse
     • @BeforeClass-Methoden (auch die gee...
Beispiel: Reihenfolge und Vererbung
 public class HierarchicalBaseTest {
     @Before public void beforeBase2() { ... }
  ...
Beispiel: Reihenfolge und Vererbung
•   Ausführung ergibt:
    Base.BeforeClass 1
    Base.BeforeClass 2
      Base.Before...
Beispiel: Reihenfolge und Vererbung
  public class HierarchicalTest extends HierarchicalBaseTest {
    @Before public void...
Beispiel: Reihenfolge und Vererbung
•   Ausführung ergibt:                         Fortsetzung
Base.BeforeClass 1        ...
Organisation von Tests
•   Zu berücksichtigende Faktoren bei der Organisation
     • Namenskonventionen
           • Klass...
Namenskonventionen
•   Klassen
     • Zu testende Klasse
           • ClassName
     •   Testklasse
           • ClassName...
Verzeichnisse und Pakete
•   Standard
     • Zwei Verzeichnisse src und test
     • Klasse und Testklasse im gleichen Pake...
Gruppieren von Tests
•   Unterschiedliche Tests
     • Unit, Integration, etc.
     • Laufzeiten
     • Abhängigkeiten
   ...
Gruppieren mit @SuiteClasses
•    Folgende Klasse definiert eine Suite
      • Zwei Testklassen werden ausgeführt
    impo...
Gruppieren mit Ant
•   Der <junit>-Task ruft mit <batchtest> mehrere Tests auf
    <junit fork="true">
      <classpath re...
Ant: Erzeugen von Reports
•   Für jede Testklasse wird eine XML-Datei erzeugt
     • Übrigens: Diese Datei ist erweiterbar...
Ant: Beispiel eines Reports




              © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com   50
Continuous Integration
•   JUnit ist z. B. in Hudson integriert




                        © 2008 - 2009 Jörn Dinkla, htt...
Beispiel: Exponentielle Glättung
•   Beispiel: Exponentielle Glättung


•   public class ExponentialSmoothing {

   public...
Typische Problemstellungen
•   Weiterlaufen nach dem ersten Fehler
•   Stoppen nach dem ersten Fehler
•   Nur einen Test a...
Fortgeschrittenes
•   In JUnit 4.4 gibt es neue, experimentelle Features
      • Wenig Literatur
•   Parametrisierte Tests...
Parametrisierte Tests
•   Testfälle sollen möglichst viele Fälle abdecken
•   Deshalb ist der gleiche Code mit unterschied...
Parametrisierte Tests
 @RunWith(Parameterized.class)
 public class ParameterizedMyMathTest {
  int param; int expected;
  ...
Annahmen mit assume
•   Methoden aus der Klasse Assume
     • assumeTrue(booleanExpr);
     • assumeThat
              • s...
Theorien
•   Beim JUnit-Testen wird die Funktionalität anhand von
    Einzelfällen spezifiert.
     • Keine generellen bzw...
Theorien
•   Folgende Methode ...
    @Theory

   public void defnOfSquareRoot(double n) {

   
  assumeTrue(n >= 0);

   ...
Theorien
•   Die zu testenden Daten werden mit @DataPoint
    spezifiziert.
    @DataPoint
    public static double minusO...
assumeThat, assertThat und
•   Deklarative Beschreibung von Annahmen und
    Zusicherungen
     •   assumeThat([value], [m...
assertThat und Hamcrest
•   Objekte
     •   equalTo, hasToString, instanceOf, isCompatibleType, notNullValue,
         nu...
Trouble-Shooting
•   junit.jar wird nicht gefunden
      • CLASSPATH
•   Bestimmte Tests werden nicht ausgeführt
      • F...
Kompabilität zu JUnit 3
•   Ausführung von JUnit-4-Tests mit dem JUnit-3-Runner
•   Adapter in suite() Methode jeder Klass...
Nachteile von JUnit 4
•   Die Entwickler von TestNG sehen ein paar Nachteile bei
    JUnit4 [BS08]
•   Zustandslosigkeit d...
JUnit 3


       Mein Tip:
Nicht mehr verwenden!


     © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
JUnit 3
•   JUnit 3 basiert auf Vererbung
     • Jede Testklasse muss von TestCase erben
•   ABER: Vererbung ist problemat...
Die Testfunktionen
•   Superklasse TestCase
     • Wird abgeleitet und erweitert.

 public class MyMathTest extends TestCa...
Die abstrakte Klasse TestCase
public abstract class TestCase implements Test
{
  private final String fName;

    public Te...
Nachteile von JUnit 3
•   JUnit3 ist „intrusive“, d.h. macht starke Einschränkungen
     • Jede Testklasse muss von TestCa...
Nachteile von JUnit 3
•   Konfiguration mit setUp und tearDown
     • nur pro Methode, nicht pro Testklasse
•   Keine Abhä...
Tests und Design



    © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
Tests und Design
•   Spannungsfeld zwischen Anwendung und Testklassen
     • Anwendung
           • Abhängigkeiten
       ...
Tests und Design: Anforderungen
•   Anforderungen an Tests
     • Wartbar, einfach verstehbar
     • Stabil gegenüber
    ...
Tests und Design: Schnittstellen
•   Schlimmster Fehler
     • Entwicklung gegen Implementierungen
     • Nicht gegen Schn...
Tests und Design: Schnittstellen
•   Zweitschlimmster Fehler
     • Die konkrete Implementierung im Code festlegen
     • ...
Tests u. Design: Dependency Injection
•   1. Lösungsmöglichkeit
      • Übergabe im Konstruktor
      • Entwurfsmuster: De...
Tests u. Design: Dependency Injection
•   2. Lösungsmöglichkeit
      • Übergabe im Setter
      • Entwurfsmuster: Depende...
Tests und Design: Fabrik / Factory
•   3. Lösungsmöglichkeit
      • Entwurfsmuster: Fabrik / Factory
      • Übergabe der...
Tests und Design: static
•   Statische Initialisierungen und finale Attribute sind nicht
    austauschbar.
    public clas...
Tests/Design: Singletons und static
•   Aufgabe: findById() durch Testfunktion zu ersetzen, die
    nicht auf die Datenban...
Refaktorisieren
•   Umgestaltung des bestehenden Quellcodes
     • Invariante: Semantik / beobachtbares Verhalten

•   Ver...
Refaktorisieren
•   Häufige Refaktorisierungen
     • Umbenennungen
     • Verschieben
     • Änderung der Signatur einer ...
Tests und Design
•   Was tun, damit die Tests erfolgreich sind [B02] ?
     • Faking it
           • Erste schnelle Lösung...
Design von Tests: Muster
•   Allgemeine Richtlinien
     • Happy path
     • Failure testing
•   Java POJOs: Plain Old Jav...
Richtlinie: „Right BICEP“
•   Nach [HT03]
     • Right
           • Ergebnisse gemäß Spezifikation?, „happy path“
     •  ...
Richtlinie für Grenzfälle: „CORRECT“
•   Nach [HT03]
     • Conformance
           • Format,   YYYY-MM-DD
     •   Orderin...
Testen von Java POJOs
•   Am häufigsten zu testen
     • Methoden equals() und hashcode()
     • void-Methoden
     • Kons...
Java: equals() und hashcode()
•   Wichtig: equals() wird von assertEquals() benutzt
•   Für equals() und hashCode() gibt e...
Java: equals() und hashcode()
•   Einfach, aber arbeitsaufwendig
     • Viele Klassen überschreiben equals()

•   Einfache...
Java: void-Methoden
•   Testen der Seiteneffekte, der Zustandsänderungen
     • Vorbedingungen
           • Zustand des Ob...
Java: Konstruktoren
•   Kommt selten vor
•   Henne-und-Ei-Problem:
      • Ein Objekt ist zum Vergleich notwendig
•   Ist ...
Java: Getter und Setter
•   Nur, wenn diese Logik beinhalten
     • Validierung
     • Berechnete Attribute

•   Meistens ...
Java: Schnittstellen / Interfaces
•   Schnittstellen definieren nur die Syntax, keine Semantik
•   Problem: Klassen, die S...
Java: Schnittstellen / Interfaces
•       Lösung: Spezifikation des Verhaltens in abstrakter
        Testklasse

        a...
Java: Schnittstellen / Interfaces
•       Testklassen der Implementierungen erben sendMail()
•       Und müssen nur die ge...
Java: JavaBeans
•   Auszug aus einem Beispiel
    public class MailBean extends Object implements Serializable {
    priva...
Java: JavaBeans
•   JavaBean
     • Getter und Setter
                  • Nur, wenn sie Logik beinhalten
            •   P...
Java: JavaBeans
•   Im Test
      • Rufen wir einen Setter auf
      • Und vergleichen mit dem letzen Wert des Listeners

...
Java: Collections
•   Lösung: equals() benutzen
•   Folgende Bedingungen für die Gleichheit nach equals()
     • Collectio...
Java: Komplexe Objekte
•   Klassen haben evtl. viele Attribute A1,...,An
•   Zustandsraum
     • Menge der unterschiedlich...
Java: Komplexe Objekte
•   Container enthalten andere Objekte und kontrollieren
    deren Lifecycle
•   In UML: Aggregatio...
Stubs, Fakes und Mocks
•   Beim Film:
     • Attrappen, Kulissen, Dummys, Doubles, etc.

•   Beim Testen
     • Das zum Te...
Stubs, Fakes und Mocks
•   Anwendungsgebiete
     • Wenn Ausführung zu lange dauert
           • Datenbanken
           • ...
Stubs, Fakes und Mocks
•   Stub
     • Damit das Programm kompiliert
     • Ansonsten leer
•   Fake
     • Gibt künstliche...
Stubs, Fakes und Mocks: Stub
•   Stub
     • Damit das Programm kompiliert
    public class MailerStub implements IMailer ...
Stubs, Fakes und Mocks: Fake
•   Fake
     • Gibt künstliche Daten zurück
    public class MailerFake implements IMailer {...
Stubs, Fakes und Mocks: Mock
•   Mock
     • Implementieren die Schnittstelle, API
     • Und das spezifizierte Verhalten
...
Mocks: easyMock
•   easyMock
     • Generiert Mock-Objekte
     • Benötigt Java 5
     • Code ist refaktorisierbar

•   Mo...
Mocks: easyMock
 @Test public void mockTest() {
     IMailer mock = createMock(IMailer.class);
     expect(mock.getMails()...
Mocks: jMock
•   Über jMock liest man selten Gutes
     • Methodennamen werden als Strings übergeben
           • Keine Re...
Data Driven Testing
•   Wo können Daten für Tests herkommen?
     • Java Properties
     • Umgebungsvariablen
     • Resou...
Nebenläufigkeit / Concurrency
•   Neue Fragestellungen
     • Thread-Sicherheit
           • „thread-safety“
           • D...
Nebenläufigkeit: Problemstellung
•   Zustand
     • Zustand ist die Menge der Attribute / Felder
     • Methoden ändern den...
Nebenläufigkeit: Zustand
•   Zustandsvariablen und die Schwierigkeit des Testens
     • „don't share“
           • Nur atom...
Nebenläufigkeit: synchronized
•   Die Variable count ist veränderlich
•   Es gibt „lost updates“ in inc()
    public class ...
Nebenläufigkeit: Atomic
•   Möglichkeit für einzelne Attribute
     • Atomare Variablen
     • in java.util.concurrent.atom...
Nebenläufigkeit: Thread-Safety
•   Durch statistische Auswertung
     • Sprich: Wiederholen des Tests bis der Fehler
      ...
Nebenläufigkeit: Weitere Punkte
•   Einfache Lösung:
     • "Thread confinement"
     • Beispiele: Swing und Eclipse SWT
  ...
Dependency Injection
•   Frameworks für einfachere Konfiguration
     • (als die ganzen Setter bzw. Konstruktoren aufzuruf...
Performanz- und Lasttests
•   Performancetests
     • Absolut
           • Zeitabschätzung mit oberer Schranke
     •   Re...
Performanz: Absolut
•   Absolut
     • Zeitabschätzung mit oberer Schranke
	   @Test(timeout = 1000)

   public void absol...
Performanz: Relativ
•   Relativ
     • Messen der Zeit für n=k, k=10000
     • Dann für n=k*10
     • Abschätzung nach O(n...
JUnitPerf
•   Erweiterung von TestCase
     • Daher JUnit 3.8
•   Dekorator-Pattern
     • erlaubt die Erweiterung bestehe...
JUnitPerf
•   LoadTest
     • simuliert mehrere User und Iterationen
•   Beispiel
     • Für 10 Benutzer und 100 Iteration...
JMeter
•   Lade und Performanztests für Server
     • Web, HTTP, HTTPS
     • SOAP
     • Datenbanken / JDBC
     • LDAP
 ...
The Grinder
•   Verteilte Test-Framework
     • Load-Tests
     • Anpassbar an alle Java APIs
         • HTTP, SOAP, REST,...
Äquivalenz, nicht Implikation
•   Beispiel: Binäre Suche in einem Array
•   Nach
     • Oram, Wilson. „Beautiful Code“, O'...
Äquivalenz, nicht Implikation
•   Die Theorie über die binäre Suche search(arr, i)

•   Annahmen „hin“
     • search(arr, ...
Erweiterungen von JUnit



       © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
JUnit 3 und JUnit 4
•   Erweiterungen
     • Die auf JUnit 3 aufsetzen und von TestCase erben
     • Können nicht immer in...
Nützliche Zusatzprogramme



        © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
PMD

•   PMD ist ein Werkzeug zur
    Quellcodeanalyse.
     • Es kann mögliche Fehler, suboptimalen
       Code, etc. fin...
Findbugs
•   Findbugs analysiert die Qualität des Quellcodes.




                       © 2008 - 2009 Jörn Dinkla, http:/...
Checkstyle
•   Checkstyle analysiert die Code-Qualität.




                       © 2008 - 2009 Jörn Dinkla, http://www.d...
JavaNCSS
•   JavaNCSS berechnet die Anzahl der reinen Codezeilen.
     • Non-commenting source statements




            ...
Testabdeckung



  © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
Testabdeckung: Grundlagen
•   „Überdeckungstest“
•   Metrik der Code-Qualität
•   Welche Teile des Codes werden beim Test ...
Testabdeckung: Warnung
•   Die Testabdeckung ...
     • Sollten NIE als Metrik über die Qualität der Tests oder
       des...
Testabdeckung: Werkzeuge
•   Beispiele
     • Kommerziell
           • Atlassian Clover
              •Ab 1200 $ für Einze...
Testabdeckung: Arbeitsweise

 •   Arbeiten durch Modifizierung des Codes
      • Methoden zur Sammlung von statistischen D...
Testabdeckung: Cobertura
•   Ändert den Bytecode




                     © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com...
Testabdeckung: Cobertura
•   Die Methode createIgnoreBranches wurde nicht getestet




                      © 2008 - 2009...
Testabdeckung: NetBeans
•   Code Coverage Plugin
•   Benutzt EMMA, ab Java 6




                     © 2008 - 2009 Jörn D...
Testabdeckung: NetBeans




            © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com   145
DbUnit



© 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
DbUnit
•   DbUnit ist ein Testwerkzeug für die Datenbank.
     • Testdaten werden in XML-Dateien definiert.
     • Damit w...
DbUnit
•   Inhalte von Tabellen werden in XML gespeichert

    <PREDICTION_GROUP_TYPE ID="1" NAME="Prognosegruppe" />
    ...
Allgemeines zum Testen von DB
•   Testen auf einer „großen“ Datenbank hat Nachteile:
     • Die Performanz ist schlecht.
 ...
XMLUnit



© 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
XMLUnit
•   XML-Dokumente sind überall
•   Zu Testen sind ...
     • Konformität, Validierung
         • Document Type Def...
Erinnerung: XML

 •   XML
      • Elemente („tags“) und Attribute
      • Starttags und Endtags, verkürzter Endtag ‚/>‘
  ...
Erinnerung: XML-Baumstruktur
•   <project name="Tutorial" default="build">

    <target name="build">

     <echo message=...
XMLUnit: Möglichkeiten
•   XMLUnit kann
     • Unterschiede zwischen Dokumenten
           • Diff und DetailedDiff
     • ...
XMLUnit: Möglichkeiten
•   XMLUnit unterscheidet beim Vergleich
     • identisch („identical“)
     • similiar
           ...
XMLUnit
•   Unterschiede werden in Diff-Objekten gespeichert.
    @BeforeClass
    public static void setUp() {
        XM...
Rich Clients



 © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
Rich Clients-Frameworks für Java
•   Viele Frameworks
     • Swing und Abstract Windowing Toolkit (AWT)
     • Eclipse Sta...
Rich Clients-Frameworks für Java
•   Aspekte eines GUI-Frameworks
     • Kleinere Aufgaben und Utilities
           • Vali...
Testen von Rich Clients
•   Schwierig zu Testen
     • Abhängigkeit von GUI-Klassen
     • GUI reagiert nur auf Ereignisse...
MVC und Präsentationsmodell
•   Entwurfsmuster „Model-View-Controller“
     • Model: Datenmodell
     • View: Darstellung ...
MVC
•   Bei Swing
     • View und Controller vereint bzw. eng-gekoppelt
     • Verursacht beim Testen Schwierigkeiten
    ...
Neuere Lösung: Presentation-Model
•   Presentation Model
     • Kein Zustand im GUI
           • Da schwierig in Tests an ...
Data Binding
•   Für jedes GUI-Element, das vom Benutzer geändert
    werden kann gibt es ein Modell-Element
•   Problem
 ...
Testen von GUIs
•   Testing-Frameworks müssen die folgenden Aufgaben
    unterstützen

     •   Finden von Komponenten in ...
Testen von GUIs
 •   Viele Frameworks und Tools
      • Siehe http://www.testingfaqs.org/t-gui.html
 •   Open Source
     ...
Beispielanwendung
•   Der Celsius-zu-Fahrenheit-Umwandler aus dem Java-
    Web-Tutorial

•   Swing-Komponenten
•   JFrame...
Jemmy
•   Im Rahmen von NetBeans entstanden
•   API für den Zugriff auf die Interna von Swing
     • Hängt sich in die Ere...
Jemmy: Beispiel
•   Test des Celsius-zu-Fahrenheit-Umwandlers
    public class Jemmy1Test {
     JFrame frame;
     JFrame...
Jemmy: Beispiel
•       Die Test-Methode
         • Suchen der Elemente und Eingabe machen
         • Knopf drücken
      ...
Jemmy: Beispiel
•    Zum Suchen von Elementen in der Hierarchie der GUI
     werden ComponentChooser verwendet
      • Der...
Web-Anwendungen



    © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
Testen von Web-Anwendungen
•   Arten
     • Statische Webseiten
     • Dynamische Webseiten
           • JSP, Velocity
   ...
Testen von Web-Anwendungen

•   Client
     • Browser
           • „Makro-Rekorder“
              •Aufzeichnen von Benutze...
Testen von Web-Anwendungen
•   Viele Frameworks und Tools
     • http://java-source.net/open-source/web-testing-tools

•  ...
Beispielanwendung
•   Das „Hallo-Welt“ der Webanwendungen



                                                             ...
Beispielanwendung
•   Datei index.jsp

    <%@page contentType="text/html" ageEncoding="UTF-8"%>
    <html>
    <body>
   ...
Beispielanwendung
•    Datei show.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<html>
    <body>            ...
HttpUnit testet Web-Applikationen
•   HttpUnit simuliert einen Web-Client

•   Kann Requests senden und Responses empfange...
HttpUnit
•   HttpUnit unterstützt u. a. die folgenden Klassen
     • WebConversation
           • Eine Web-Verbindung
    ...
HttpUnit: JUnit4
•   Wir überprüfen dieses mit einem Test.
    public class HttpUnitTest {

    final private String text =...
Selenium IDE
•   Makro-Rekorder
•   Browser-Erweiterung




                     © 2008 - 2009 Jörn Dinkla, http://www.din...
Selenium IDE
•   Die aufgezeichneten Tests lassen sich als JUnit3-Test
    exportieren.
    public class SeleniumTest exte...
JEE / J2EE



© 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
JEE / J2EE
•   Frage: Im Server oder Stand-alone
     • Problem: Abhängigkeiten
     • POJOs sind einfach zu testen
     •...
Apache Cactus
•   Generelles Framework
     • Serverseitiger Code
     • Servlets, EJBs, Tag-Bibliotheken
     • Schwerpun...
JUnitEE
•   JUnitEE ermöglicht Unit-Tests auf dem Applikationsserver.
•   Es wird ein EAR/WAR/JAR erstellt, das JUnitEE un...
TestNG



© 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
TestNG
•   Aus Unzufriedenheit mit JUnit3 entwickelt [BS08]
•   Diente als Vorbild für Neuerungen in JUnit4
•   Basiert au...
TestNG: Die Annotationen
•   Annotieren der Methoden wie bei JUnit 4 mit
     • @Test
•   Flexibler als bei JUnit4
     • ...
TestNG: Die Annotationen
•   Before- und After-Annotationen
     • @BeforeSuite, @AfterSuite
           • Testsuite
     •...
TestNG: Die Annotationen
•   @DataProvider
     • Erzeugt Daten für eine Test-Methode
•   @Factory
     • Methode, die Tes...
Akzeptanztests



   © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
Akzeptanztests
•   Erweiterung des TDD auf Akzeptanztests [K07]
     • Acceptance TDD

•   User Story als Spezifikation
  ...
Fit - Framework for Integrated Test
•   Spezifikation in HTML-Dateien
     • Vorteil: Fachabteilung, „executable specifica...
Fit: Fixture
 public class CalculateCredit extends fit.ColumnFixture {
     public int months;
     public boolean reliabl...
Fit: Ergebnis
•   Ergebnis




                © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com   197
Fit: Weiteres
•   Fixtures
     • ColumnFixture
           • Abbildung von Spalten der Testdaten zu Attributen der
       ...
FitNesse
•   Front-End für Fit
•   Kollaborative Software-Entwicklung
     • Acceptance Testing Framework
     • Wiki
    ...
Referenzen



 © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
Bücher über JUnit 3
•   [MH03]
     • Vincent Massol, Ted Husted. JUnit in Action.
       Manning. 2003.

•   [R04]
     •...
Bücher über TDD
•   [B02]
     • Kent Beck. Test-Driven Development. By
       Example. Addison-Wesley. 2002.

•   [K07]
 ...
Bücher über JEE
•   [BS08]
     • Cedriv Beust, Hani Suleiman. Next
       Generation Java Testing: TestNG and
       Adva...
Test-Driven-Development mit JUnit 4
Upcoming SlideShare
Loading in...5
×

Test-Driven-Development mit JUnit 4

8,384

Published on

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

Published in: Technology
0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
8,384
On Slideshare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
1
Comments
0
Likes
5
Embeds 0
No embeds

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&amp;#xFC;hrung
  • TODO Running Fortgeschritten
    Einzelne mit &lt;test&gt;
  • TODO
  • brittleness Br&amp;#xFC;chigkeit, Spr&amp;#xF6;digkeit, Zerbrechlichkeit, Morschheit
  • Zustandslos .NET ?
  • TODO Warnung, dass theo nicht m&amp;#xF6;glich
  • TODO
  • TODO nanoTime
  • TODO
  • TODO 1.1 lassen weg Fehlalarm
  • TODO Webseiten URLS
  • TODO
  • Transcript of "Test-Driven-Development mit JUnit 4"

    1. 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. 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. 3. Überblick © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    4. 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. 5. Grundlagen des Testens © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    6. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 19. JUnit 4 © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    20. 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. 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. 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. 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. 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. 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. 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. 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. 28. Beispiel für Fehler • NetBeans • Eclipse © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 28
    29. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 50. Ant: Beispiel eines Reports © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 50
    51. 51. Continuous Integration • JUnit ist z. B. in Hudson integriert © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 51
    52. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 66. JUnit 3 Mein Tip: Nicht mehr verwenden! © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    67. 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. 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. 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. 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. 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. 72. Tests und Design © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    73. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 130. Erweiterungen von JUnit © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    131. 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. 132. Nützliche Zusatzprogramme © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    133. 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. 134. Findbugs • Findbugs analysiert die Qualität des Quellcodes. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 134
    135. 135. Checkstyle • Checkstyle analysiert die Code-Qualität. © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 135
    136. 136. JavaNCSS • JavaNCSS berechnet die Anzahl der reinen Codezeilen. • Non-commenting source statements © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 136
    137. 137. Testabdeckung © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    138. 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. 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. 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. 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. 142. Testabdeckung: Cobertura • Ändert den Bytecode © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 142
    143. 143. Testabdeckung: Cobertura • Die Methode createIgnoreBranches wurde nicht getestet © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 143
    144. 144. Testabdeckung: NetBeans • Code Coverage Plugin • Benutzt EMMA, ab Java 6 © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 144
    145. 145. Testabdeckung: NetBeans © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 145
    146. 146. DbUnit © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    147. 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. 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. 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. 150. XMLUnit © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    151. 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. 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. 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. 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. 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. 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. 157. Rich Clients © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    158. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 172. Web-Anwendungen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    173. 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. 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. 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. 176. Beispielanwendung • Das „Hallo-Welt“ der Webanwendungen Start Eingabe Ausgabe © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 176
    177. 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. 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. 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. 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. 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. 182. Selenium IDE • Makro-Rekorder • Browser-Erweiterung © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 182
    183. 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. 184. JEE / J2EE © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    185. 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. 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. 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. 188. TestNG © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    189. 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. 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. 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. 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. 193. Akzeptanztests © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    194. 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. 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. 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. 197. Fit: Ergebnis • Ergebnis © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com 197
    198. 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. 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. 200. Referenzen © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
    201. 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. 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. 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

    ×