SlideShare une entreprise Scribd logo
1  sur  204
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
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
Überblick



© 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
Ü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
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 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
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
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
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
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
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
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
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
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
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
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
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
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
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 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
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
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
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
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
JUnit4: Ant-Integration
•   Integration in Ant
      • <junit> und <junitreport> Tasks
•   Später mehr ...




                      © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com   25
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
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
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


     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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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, http://www.dinkla.com   51
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 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
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
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
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
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
Tests und Design



    © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Ä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
Ä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
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 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
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. finden
     • Ist mit Regeln konfigurierbar und
       erweiterbar




                     © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com   133
Findbugs
•   Findbugs analysiert die Qualität des Quellcodes.




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




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




                      © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com   136
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 ausgeführt ?
•   Granularitäten
     • Klasse
     • Methode
     • Statement
     • Block
     • Branch/Decision
•   Schwierigkeit
     • kombinatorische Explosion

                      © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com   138
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
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
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
Testabdeckung: Cobertura
•   Ändert den Bytecode




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




                      © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com   143
Testabdeckung: NetBeans
•   Code Coverage Plugin
•   Benutzt EMMA, ab Java 6




                     © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com   144
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 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
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
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
XMLUnit



© 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
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
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
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
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
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
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
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 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
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
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
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
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
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
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
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
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
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
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
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
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
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
Web-Anwendungen



    © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
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
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
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
Beispielanwendung
•   Das „Hallo-Welt“ der Webanwendungen



                                                                         Start




                                                                        Eingabe




                                                                        Ausgabe
                     © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com             176
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
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
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
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
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
Selenium IDE
•   Makro-Rekorder
•   Browser-Erweiterung




                     © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com   182
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
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
     • 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
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
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
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 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
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
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
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
Akzeptanztests



   © 2008 - 2009 Jörn Dinkla, http://www.dinkla.com
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
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
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
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
           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
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
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]
     • 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
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
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
Test-Driven-Development mit JUnit 4

Contenu connexe

Tendances

Flexibilitaet mit CDI und Apache DeltaSpike
Flexibilitaet mit CDI und Apache DeltaSpikeFlexibilitaet mit CDI und Apache DeltaSpike
Flexibilitaet mit CDI und Apache DeltaSpike
os890
 
Boost your APEX Deployment and Provisioning with Docker
Boost your APEX Deployment and Provisioning with DockerBoost your APEX Deployment and Provisioning with Docker
Boost your APEX Deployment and Provisioning with Docker
Steven Grzbielok
 

Tendances (20)

Jenkins Acceleration
Jenkins AccelerationJenkins Acceleration
Jenkins Acceleration
 
Flexibilitaet mit CDI und Apache DeltaSpike
Flexibilitaet mit CDI und Apache DeltaSpikeFlexibilitaet mit CDI und Apache DeltaSpike
Flexibilitaet mit CDI und Apache DeltaSpike
 
Einstieg in das Windows Installer XML (WiX) ToolSet
Einstieg in das Windows Installer XML (WiX) ToolSetEinstieg in das Windows Installer XML (WiX) ToolSet
Einstieg in das Windows Installer XML (WiX) ToolSet
 
DevOps der Triple-E Klasse - Eclipse DemoCamp
DevOps der Triple-E Klasse - Eclipse DemoCampDevOps der Triple-E Klasse - Eclipse DemoCamp
DevOps der Triple-E Klasse - Eclipse DemoCamp
 
Docker Workshop Experten Forum Stuttgart 2015, Agile Methoden GmbH
Docker Workshop Experten Forum Stuttgart 2015, Agile Methoden GmbHDocker Workshop Experten Forum Stuttgart 2015, Agile Methoden GmbH
Docker Workshop Experten Forum Stuttgart 2015, Agile Methoden GmbH
 
BED-Con - Tools für den täglichen Kampf als Entwickler
BED-Con - Tools für den täglichen Kampf als EntwicklerBED-Con - Tools für den täglichen Kampf als Entwickler
BED-Con - Tools für den täglichen Kampf als Entwickler
 
Docker - Containervirtualisierung leichtgemacht
Docker - Containervirtualisierung leichtgemachtDocker - Containervirtualisierung leichtgemacht
Docker - Containervirtualisierung leichtgemacht
 
Introduction to Apache Maven 3 (German)
Introduction to Apache Maven 3 (German)Introduction to Apache Maven 3 (German)
Introduction to Apache Maven 3 (German)
 
Continuous Delivery
Continuous DeliveryContinuous Delivery
Continuous Delivery
 
Vagrant, Puppet, Docker für Entwickler und Architekten
Vagrant, Puppet, Docker für Entwickler und ArchitektenVagrant, Puppet, Docker für Entwickler und Architekten
Vagrant, Puppet, Docker für Entwickler und Architekten
 
"git.net" gibt's nicht?
"git.net" gibt's nicht?"git.net" gibt's nicht?
"git.net" gibt's nicht?
 
Perl Renaissance Reloaded
Perl Renaissance ReloadedPerl Renaissance Reloaded
Perl Renaissance Reloaded
 
Docker - Automatisches Deployment für Linux-Instanzen
Docker - Automatisches Deployment für Linux-Instanzen Docker - Automatisches Deployment für Linux-Instanzen
Docker - Automatisches Deployment für Linux-Instanzen
 
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbH
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbHEntwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbH
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbH
 
Docker Einführung @GPN15
Docker Einführung @GPN15Docker Einführung @GPN15
Docker Einführung @GPN15
 
Boost your APEX Deployment and Provisioning with Docker
Boost your APEX Deployment and Provisioning with DockerBoost your APEX Deployment and Provisioning with Docker
Boost your APEX Deployment and Provisioning with Docker
 
Tipps und Tricks im Umgang mit Docker
Tipps und Tricks im Umgang mit DockerTipps und Tricks im Umgang mit Docker
Tipps und Tricks im Umgang mit Docker
 
Wie skaliert man Software as a Service Applikationen in der Windows Azure Cloud
Wie skaliert man Software as a Service Applikationen in der Windows Azure CloudWie skaliert man Software as a Service Applikationen in der Windows Azure Cloud
Wie skaliert man Software as a Service Applikationen in der Windows Azure Cloud
 
WebLogic im Docker Container
WebLogic im Docker ContainerWebLogic im Docker Container
WebLogic im Docker Container
 
Docker Workbench
Docker WorkbenchDocker Workbench
Docker Workbench
 

En vedette

An example of Future composition in a real app
An example of Future composition in a real appAn example of Future composition in a real app
An example of Future composition in a real app
Phil Calçado
 
Introduction to apache_cassandra_for_developers-lhg
Introduction to apache_cassandra_for_developers-lhgIntroduction to apache_cassandra_for_developers-lhg
Introduction to apache_cassandra_for_developers-lhg
zznate
 

En vedette (6)

An example of Future composition in a real app
An example of Future composition in a real appAn example of Future composition in a real app
An example of Future composition in a real app
 
Bessere Tests mit JUnit 4.x
Bessere Tests mit JUnit 4.xBessere Tests mit JUnit 4.x
Bessere Tests mit JUnit 4.x
 
Scala sydoct2011
Scala sydoct2011Scala sydoct2011
Scala sydoct2011
 
Raphaël JS Conf
Raphaël JS ConfRaphaël JS Conf
Raphaël JS Conf
 
Scala.io 2013 - M’enfin Scalac, où glandes-tu encore ?
Scala.io 2013 - M’enfin Scalac, où glandes-tu encore ?Scala.io 2013 - M’enfin Scalac, où glandes-tu encore ?
Scala.io 2013 - M’enfin Scalac, où glandes-tu encore ?
 
Introduction to apache_cassandra_for_developers-lhg
Introduction to apache_cassandra_for_developers-lhgIntroduction to apache_cassandra_for_developers-lhg
Introduction to apache_cassandra_for_developers-lhg
 

Similaire à Test-Driven-Development mit JUnit 4

Bi testing media_factory_0.10
Bi testing media_factory_0.10Bi testing media_factory_0.10
Bi testing media_factory_0.10
inovex GmbH
 
Unit Tests für Totalverweigerer
Unit Tests für TotalverweigererUnit Tests für Totalverweigerer
Unit Tests für Totalverweigerer
Peter Hauke
 
Testmanagement mit Visual Studio 2013
Testmanagement mit Visual Studio 2013Testmanagement mit Visual Studio 2013
Testmanagement mit Visual Studio 2013
Nico Orschel
 
Tipps zur Performanceoptimierung für Liferay Portal
Tipps zur  Performanceoptimierung für Liferay PortalTipps zur  Performanceoptimierung für Liferay Portal
Tipps zur Performanceoptimierung für Liferay Portal
Stefan Hilpp
 
Wirtschaftlich Software testen (ESE-Kongress 2012)
Wirtschaftlich Software testen (ESE-Kongress 2012)Wirtschaftlich Software testen (ESE-Kongress 2012)
Wirtschaftlich Software testen (ESE-Kongress 2012)
Matthias Kraaz
 

Similaire à Test-Driven-Development mit JUnit 4 (20)

iOS Testautomation bei mobile.de
iOS Testautomation bei mobile.deiOS Testautomation bei mobile.de
iOS Testautomation bei mobile.de
 
Bi testing media_factory_0.10
Bi testing media_factory_0.10Bi testing media_factory_0.10
Bi testing media_factory_0.10
 
Ringvorlesung: FIO Systems AG stellt Projektziel zum Thema Software Design Pa...
Ringvorlesung: FIO Systems AG stellt Projektziel zum Thema Software Design Pa...Ringvorlesung: FIO Systems AG stellt Projektziel zum Thema Software Design Pa...
Ringvorlesung: FIO Systems AG stellt Projektziel zum Thema Software Design Pa...
 
Foreman: Docker Integration (Webinar vom 05. Oktober_2016)
Foreman: Docker Integration (Webinar vom 05. Oktober_2016)Foreman: Docker Integration (Webinar vom 05. Oktober_2016)
Foreman: Docker Integration (Webinar vom 05. Oktober_2016)
 
eCATT & OpenSource - Automatisierter Test in heterogenen Systemlandschaften
eCATT & OpenSource - Automatisierter Test in heterogenen SystemlandschafteneCATT & OpenSource - Automatisierter Test in heterogenen Systemlandschaften
eCATT & OpenSource - Automatisierter Test in heterogenen Systemlandschaften
 
Robuste Design Systems mit Storybook und Angular: vom Konzept zur lebendigen ...
Robuste Design Systems mit Storybook und Angular: vom Konzept zur lebendigen ...Robuste Design Systems mit Storybook und Angular: vom Konzept zur lebendigen ...
Robuste Design Systems mit Storybook und Angular: vom Konzept zur lebendigen ...
 
Automatisiertes Testen von Software in C++ (mit dem Test Framework Google Test)
Automatisiertes Testen von Software in C++ (mit dem Test Framework Google Test)Automatisiertes Testen von Software in C++ (mit dem Test Framework Google Test)
Automatisiertes Testen von Software in C++ (mit dem Test Framework Google Test)
 
DWX 2014 - Testmanagement mit Visual Studio 2013
DWX 2014 - Testmanagement mit Visual Studio 2013DWX 2014 - Testmanagement mit Visual Studio 2013
DWX 2014 - Testmanagement mit Visual Studio 2013
 
Presenting to win - how I changed some old slides
Presenting to win - how I changed some old slidesPresenting to win - how I changed some old slides
Presenting to win - how I changed some old slides
 
Unit Tests für Totalverweigerer
Unit Tests für TotalverweigererUnit Tests für Totalverweigerer
Unit Tests für Totalverweigerer
 
Kollaboration in Java Projekten - Anspruch und Realität
Kollaboration in Java Projekten - Anspruch und RealitätKollaboration in Java Projekten - Anspruch und Realität
Kollaboration in Java Projekten - Anspruch und Realität
 
Softwerkskammer Chemnitz Special Pecha Kucha Night
Softwerkskammer Chemnitz Special Pecha Kucha NightSoftwerkskammer Chemnitz Special Pecha Kucha Night
Softwerkskammer Chemnitz Special Pecha Kucha Night
 
Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)
 
Referat: Scrum Rocks – Testing Sucks?! (reloaded)
Referat: Scrum Rocks – Testing Sucks?! (reloaded)Referat: Scrum Rocks – Testing Sucks?! (reloaded)
Referat: Scrum Rocks – Testing Sucks?! (reloaded)
 
Agile Entwicklungsumgebung mit DVCS, Jenkins und Trello - Agile Bodensee Konf...
Agile Entwicklungsumgebung mit DVCS, Jenkins und Trello - Agile Bodensee Konf...Agile Entwicklungsumgebung mit DVCS, Jenkins und Trello - Agile Bodensee Konf...
Agile Entwicklungsumgebung mit DVCS, Jenkins und Trello - Agile Bodensee Konf...
 
Testmanagement mit Visual Studio 2013
Testmanagement mit Visual Studio 2013Testmanagement mit Visual Studio 2013
Testmanagement mit Visual Studio 2013
 
Tipps zur Performanceoptimierung für Liferay Portal
Tipps zur  Performanceoptimierung für Liferay PortalTipps zur  Performanceoptimierung für Liferay Portal
Tipps zur Performanceoptimierung für Liferay Portal
 
Testing XAML-based Windows Store Apps mit VS 2013
Testing XAML-based Windows Store Apps mit VS 2013Testing XAML-based Windows Store Apps mit VS 2013
Testing XAML-based Windows Store Apps mit VS 2013
 
Wirtschaftlich Software testen (ESE-Kongress 2012)
Wirtschaftlich Software testen (ESE-Kongress 2012)Wirtschaftlich Software testen (ESE-Kongress 2012)
Wirtschaftlich Software testen (ESE-Kongress 2012)
 
Applikationsmodernisierung: Der Weg von Legacy in die Cloud
Applikationsmodernisierung: Der Weg von Legacy in die CloudApplikationsmodernisierung: Der Weg von Legacy in die Cloud
Applikationsmodernisierung: Der Weg von Legacy in die Cloud
 

Plus de Jörn Dinkla

Plus de Jörn Dinkla (16)

Presentation of the book "Mikado Method"
Presentation of the book "Mikado Method"Presentation of the book "Mikado Method"
Presentation of the book "Mikado Method"
 
Korrekte nebenläufige Anwendungen mit Koroutinen und TDD
Korrekte nebenläufige Anwendungen mit Koroutinen und TDDKorrekte nebenläufige Anwendungen mit Koroutinen und TDD
Korrekte nebenläufige Anwendungen mit Koroutinen und TDD
 
Nebenlaeufigkeit mit Koroutinen strukturieren
Nebenlaeufigkeit mit Koroutinen strukturierenNebenlaeufigkeit mit Koroutinen strukturieren
Nebenlaeufigkeit mit Koroutinen strukturieren
 
Plain react, hooks and/or Redux ?
Plain react, hooks and/or Redux ?Plain react, hooks and/or Redux ?
Plain react, hooks and/or Redux ?
 
A short introduction to Kotlin
A short introduction to KotlinA short introduction to Kotlin
A short introduction to Kotlin
 
Concurrency in Kotlin with coroutines
Concurrency in Kotlin with coroutinesConcurrency in Kotlin with coroutines
Concurrency in Kotlin with coroutines
 
Nebenläufigkeit mit Kotlins Koroutinen
Nebenläufigkeit mit Kotlins KoroutinenNebenläufigkeit mit Kotlins Koroutinen
Nebenläufigkeit mit Kotlins Koroutinen
 
GPU-Computing mit CUDA und OpenCL
GPU-Computing mit CUDA und OpenCLGPU-Computing mit CUDA und OpenCL
GPU-Computing mit CUDA und OpenCL
 
Schulung: Einführung in das GPU-Computing mit NVIDIA CUDA
Schulung: Einführung in das GPU-Computing mit NVIDIA CUDASchulung: Einführung in das GPU-Computing mit NVIDIA CUDA
Schulung: Einführung in das GPU-Computing mit NVIDIA CUDA
 
Die ‚komplexe‘ Perspektive - Einführung in die digitale Wirtschaft
Die ‚komplexe‘ Perspektive - Einführung in die digitale WirtschaftDie ‚komplexe‘ Perspektive - Einführung in die digitale Wirtschaft
Die ‚komplexe‘ Perspektive - Einführung in die digitale Wirtschaft
 
Geschäftsmodelle - Ein kurzer Überblick
Geschäftsmodelle -Ein kurzer ÜberblickGeschäftsmodelle -Ein kurzer Überblick
Geschäftsmodelle - Ein kurzer Überblick
 
Buchvorstellung "Libertarian Anarchy: Against the State" von Gerard Casey
Buchvorstellung "Libertarian Anarchy: Against the State" von Gerard CaseyBuchvorstellung "Libertarian Anarchy: Against the State" von Gerard Casey
Buchvorstellung "Libertarian Anarchy: Against the State" von Gerard Casey
 
Multi-GPU-Computing: Eins, zwei, drei, ganz viele
Multi-GPU-Computing: Eins, zwei, drei, ganz vieleMulti-GPU-Computing: Eins, zwei, drei, ganz viele
Multi-GPU-Computing: Eins, zwei, drei, ganz viele
 
Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing
Tipps & Tricks für den erfolgreichen Einsatz von GPU-ComputingTipps & Tricks für den erfolgreichen Einsatz von GPU-Computing
Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing
 
GPU-Computing mit CUDA und OpenCL in der Praxis
GPU-Computing mit CUDA und OpenCL in der PraxisGPU-Computing mit CUDA und OpenCL in der Praxis
GPU-Computing mit CUDA und OpenCL in der Praxis
 
Introduction To Parallel Computing
Introduction To Parallel ComputingIntroduction To Parallel Computing
Introduction To Parallel Computing
 

Test-Driven-Development mit JUnit 4

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

Notes de l'éditeur

  1. OPT evtl. Diagram Tiefe und Breite
  2. lib/junit-4.4.jar:build/classes:../JUnit-Base/build/junit-schulung-base.jar
  3. Assert ist in Java 1.4 bereits enthalten
  4. TODO Reihenfolge der Ausf&amp;#xFC;hrung
  5. TODO Running Fortgeschritten Einzelne mit &lt;test&gt;
  6. TODO
  7. brittleness Br&amp;#xFC;chigkeit, Spr&amp;#xF6;digkeit, Zerbrechlichkeit, Morschheit
  8. Zustandslos .NET ?
  9. TODO Warnung, dass theo nicht m&amp;#xF6;glich
  10. TODO
  11. TODO nanoTime
  12. TODO
  13. TODO 1.1 lassen weg Fehlalarm
  14. TODO Webseiten URLS
  15. TODO