400 likes | 518 Views
JUnit für Fortgeschrittene. Arno.Haase@Haase-Consulting.com Arno.Haase@acm.org www.Haase-Consulting.com. Übersicht. Einführung Mock Objects Programmgrenzen: I/O, Netzwerk, DB „static“ und andere Hindernisse EJBs unter freiem Himmel Zusammenfassung Fragen und Diskussion.
E N D
JUnit für Fortgeschrittene Arno.Haase@Haase-Consulting.com Arno.Haase@acm.org www.Haase-Consulting.com
Übersicht Einführung • Mock Objects • Programmgrenzen: I/O, Netzwerk, DB • „static“ und andere Hindernisse • EJBs unter freiem Himmel • Zusammenfassung • Fragen und Diskussion
Ziele des Vortrags • Separates Testen von Klassen • Abhängigkeiten auflösen • Testen bis in die Nähe der Systemgrenzen • „Reines“ JUnit, nicht darauf aufsetzende Tools (HttpUnit, Cactus, ...)
Kurze Wiederholung • JUnit macht Spaß... • ... aber in der Praxis gibt es manche Hindernisse • Funktionalität ist testbar • Normalfälle, Fehlerfälle, Integration • Methoden-, Klassen-, Systemebene • Grenzen • Performance-Tests • Multithreading • GUI
Gute JUnit-Tests • Kriterien für eine gute Test-Suite: • Schnelles Durchlaufen • Gute Abdeckung Vertrauen • „vollständig“ ist aber schlechtes Ziel • Automatische Ausführbarkeit • automatisierter Build-Prozess • Einfach zu erstellen / pflegen
Übersicht • Einführung Mock Objects • Programmgrenzen: I/O, Netzwerk, DB • „static“ und andere Hindernisse • EJBs unter freiem Himmel • Zusammenfassung • Fragen und Diskussion
Kundenverwaltung Schufaanfrage Netzwerk Kundenpersistenz Problem • Eine einzelne Klasse ist leicht zu testen. • Im echten Projekt ist es oft anders. • Wenn Klassen von einander abhängen, kann man sie nur noch zusammen testen. • Abhängigkeiten sind oft nur implizit. Statistik
Problem (2) • sogenannter „Pragmatismus“: Dann testet man eben nicht so gründlich... • Sonderfälle bei der Datenbelieferung • Fehlerfälle und Exceptions • seltene Testausführung wegen Aufwand für Deployment und Infrastruktur
StatistikTest MockDatenquelle Mock Objects • Code über Interface ansprechen • Test-Implementierung für JUnit-Test • Initialisierung: Konstruktor oder per Parameter Statistik StatistikDatenquelle KundenStatistikDatenquelle Kundenverwaltung
Praktisches Beispiel • Ein Quelltext sagt mehr als tausend Folien...
Konkretes Vorgehen • Mock Object initialisieren • Zustand setzen • Verhalten parametrisieren • Mock Object an getesteten Code übergeben • Zustand des Mock Objects verifizieren
Größere Perspektive • Testbarkeit prägt das Design! • explizite Abhängigkeiten • Refactoring • Verschiedene Anwendungsgebiete • Geschäftslogik • Systemschnittstellen • Logger etc.
Übersicht • Einführung • Mock Objects Programmgrenzen: I/O, Netzwerk, DB • „static“ und andere Hindernisse • EJBs unter freiem Himmel • Zusammenfassung • Fragen und Diskussion
Grenzen sind komplex • Probleme mit Tests: • „schnell laufen“: Interaktion kann Zeit kosten • „Abdeckung“: Verhalten externer Teile schlechter zu kontrollieren • „Automatisch“: Synchronisierung von Tests und externen Systemen • „Einfach zu erstellen“: Externer Aufwand • Auch bei externen Bibliotheken
Zugriff durch Wrapper • Die eigentliche System-Schnittstelle hinter Interface kapseln • z.B. „HttpSender“, „FilePersister“, ... • „fertige“ Mock Objects • Test-Implementierungen können Sonderfälle / Exceptions simulieren • Design-Option: Decorator, Caching, Filter etc. • Refactoring
ClientTest MockServComm NullServComm TimeoutServComm z.B. Netzwerkkommunikation • Client versendet Strings per HTTP • Netzwerkkommunikation über Schnittstelle • Mock-Implementierung für Tests • weitere nützliche Implementierungen Client ServerCommunicator HttpServComm Netzwerk
Praktisches Beispiel • Ein Quelltext sagt mehr als tausend Folien...
Datenbanken • Alternative: Durchgriff auf die Datenbank • Testet Spezialitäten des DB-Systems • Testet die eigentliche Persistenzschicht • Macht Abhängigkeiten im Datenmodell deutlich • Jeder Entwickler braucht eine Datenbank
Testdaten • „automtatisch“: Jeder Testfall erzeugt alle benötigten Daten • „schnell“: leere Datenbank • „einfach“: Bei Bedarf Refactoring gemeinsam genutzte Testdatenerzeugung
Übersicht • Einführung • Mock Objects • Programmgrenzen: I/O, Netzwerk, DB „static“ und andere Hindernisse • EJBs unter freiem Himmel • Zusammenfassung • Fragen und Diskussion
„static ist böse“ • statischer Zustand ist problematisch • schlechte Wiederverwendbarkeit • keine unabhängige Testkonfiguration • implizite Querabhängigkeiten von Tests • statischer Code ist okay
Factories • Nur auf den ersten Blick harmlos • kapseln verwendete Implementierung • Problem ist nicht die Factory selbst sondern verwendender Code • alle Nachteile von statischen Daten • Singletons sind problematisch • auch JNDI • zusätzliche Indirektionsstufen ändern nichts...
Konfigurationsdaten • zentrale Stelle für Konfigurationen • Properties, Servletparameter, EJB-Parameter, ... • per definitionen globale Daten, d.h. static • Versuchung, sie „public static“ bekannt zu machen • Alternative: Code mit Konfigurationsobjekt parametrieren!
Auswirkungen auf das Design • Lego-Baukasten • sehr flexibel • oft wiederverwendbar • separat testbare Systemteile • dynamisch konfiguriert • Gefahr, dass unzusammenhängend und dadurch kompliziert („Ravioli“) • Refactoring
Tests auf Systemebene • Zusammenhang durch Gesamttest • Black Box • Konkrete Integration des Zielsystems testen • Es gibt andere Arten, Systeme zu entwerfen • Aber mit geringerer Testabdeckung
Übersicht • Einführung • Mock Objects • Programmgrenzen: I/O, Netzwerk, DB • „static“ und andere Hindernisse EJBs unter freiem Himmel • Zusammenfassung • Fragen und Diskussion
EJBs leben im Container... • Vorteile: • Infrastruktur: JNDI, Transaktionen, ... • Erzwungene Trennung von Schnittstelle und Implementierung • Aber durch Nachteile erkauft: • nur im Container lauffähig • Deployment kostet Zeit • Deskriptoren legen Implementierungen fest • Schwerer zu Debuggen
... - und ihre Tests? • „Brute Force“: Deployment und Debugger • nicht automatisch, nicht regressionsfähig • je nach IDE zeitaufwändig • „Black Box“-Tests: Testen der deployten Software mit JUnit • Lange Testzyklen • schlechte Abdeckung • keine Mock Objects
Ziel: separat testen • Komponenten-Gedanke: • getrennt entwickelbar • frei kombinierbar • Praktische Probleme: • Konfigurations-Parameter • JNDI • DataSource • ...
„Delegate“ XyzBean XyzDelegate • Logik in separate Klasse auslagern, EJB delegiert • Interaktion mit App-Server nur in EJB • Delegate ist lauf- und testfähig ohne Container • EJB „beliefert“ JNDI etc.
AbcDelegate AbcBean „Business Interface“ XyzBI EJBObject • „Business Interface“ mit den fachlichen Methoden • Remote-Interface erbt vom fachlichen Interface • fremder Delegate kann vom BI abhängen XyzRemote
z.B. Begrüßungsservice • Begrüßungs-EJB holt den Namen von Kundenmanager-EJB BegruesserDelegate KundenMgrBI KundenMgrBean KundenMgrRemote BegruesserBean KundenMgrHome
Praktisches Beispiel • Ein Quelltext sagt mehr als tausend Folien...
Was ist passiert? • Business Interface • fachliche Schnittstelle der EJB • Delegate • unabhängig vom Container • kennt andere EJBs als Business Interface • JUnit-Test für Delegate • Mock-Implementierungen für andere EJBs / Business Interfaces
Übersicht • Einführung • Mock Objects • Programmgrenzen: I/O, Netzwerk, DB • „static“ und andere Hindernisse • EJBs unter freiem Himmel Zusammenfassung • Fragen und Diskussion
Mock Objects • Abhängigkeiten zwischen Klassen erschweren das Testen. • Abhängigkeiten auflösen durch Interfaces • Test-Code verwendet spezielle Test-Implementierungen • Kapselung von Programmgrenzen
EJBs • implizite Abhängigkeiten • vom Container (JNDI, Parameter, ...) • von anderen EJBs • separate Implementierung, EJB als dünner Wrapper reicht Aufrufe durch • Business Interface als Schnittstelle ohne technische Methoden
Los geht´s • „Es gibt nichts Gutes außer man tut es“ • gute Testabdeckung ist möglich • Es lohnt sich • Testen macht Spaß • Refactoring
Literatur • http://www.mockobjects.com • http://www.easymock.org • Dependency Inversion: http://www.objectmentor.com/resources/articles/dip.pdf • „Testen von EJBs ohne Application Server“, Java Magazin 10/02
Übersicht • Einführung • Mock Objects • Programmgrenzen: I/O, Netzwerk, DB • „static“ und andere Hindernisse • EJBs unter freiem Himmel • Zusammenfassung Fragen und Diskussion