Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
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
Nächste SlideShare
Wird geladen in …5
×

Test-Driven-Development mit JUnit 4

9.508 Aufrufe

Veröffentlicht am

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

Veröffentlicht in: Technologie
  • Als Erste(r) kommentieren

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

×