Post on 28-Nov-2014
description
Dirk Weil | GEDOPLAN GmbH
Feige sein!Testen im EE-Umfeld
dirk.weil@gedoplan.dedirk.weil@gedoplan.de
Dirk Weil• GEDOPLAN GmbH, Bielefeld• Java EE seit 1998• Konzeption und
Realisierung• Vorträge• Seminare• Veröffentlichungen
2 Feige sein!
dirk.weil@gedoplan.de
Testen
Feige sein!3
Bei mir läuft's!
Dafür haben wir kein Budget.
Gestern ging‘s noch
(und ich hab‘ nix
gemacht).Wir haben keinen
Testserver
EE-Tests sind zu
aufwändig.
dirk.weil@gedoplan.de
Testen
Feige sein!4
Testen ist feige!
… dann lassen Sie uns feige sein!
dirk.weil@gedoplan.dedirk.weil@gedoplan.de
EE-Tests• Komplexe Komponenten-Landschaft• CDI / EJB
– @Inject, @Produces, @Alternative …• Plattform
– @PersistenceContext, @Transactional, …• Web
– @Named, @XyzScoped, @Path
dirk.weil@gedoplan.de
realembeddedSE-Test
Was und wie schnell?
Feige sein!6
Aus
führ
ungs
zeit
Testtiefe
Unit Test
Multi UnitTest
IntegrationTest
Einzelklasse KomponenteSubsystemAnwendung
Service(inkl. Umgebung)
In-Container-Test
dirk.weil@gedoplan.de
Beispielprojekt
WaehrungRepository
WaehrungService
WaehrungModel+ Views
WaehrungRestService
BestellungRepository
ArtikelRepository
ShopModel+ Views
Artikel
Bestellung
Waehrung
Bestell-Position
EntityManager / PU TX Manager
dirk.weil@gedoplan.deFeige sein!8 dirk.weil@gedoplan.de
Unit Test• Test: Umrechnung in WaehrungService• Mock für WaehrungRepository• Toolset: JUnit, Mockito
WaehrungRepository
WaehrungServiceWaehrung
dirk.weil@gedoplan.deFeige sein!9 dirk.weil@gedoplan.de
Multi Unit Test• Test: Umrechnung in WaehrungService• Test-DB statt Prod-DB• Toolset: JUnit, CDI-Container
– alternativer Producer für EntityManager– TX-Interceptor
WaehrungRepository
WaehrungServiceWaehrung
EntityManager / PU TX Manager
dirk.weil@gedoplan.deFeige sein!10 dirk.weil@gedoplan.de
Multi Unit Test• Ausgenutzte Goodies
– Apache Deltaspike• Container-Start• Context Start• Injection
– CDI 1.1 / Java EE 7• @Priority aktiviert Alternative / Interceptor• Interceptor Binding @Transactional
dirk.weil@gedoplan.deFeige sein!11 dirk.weil@gedoplan.de
Testdaten-Bereitstellung• Bulk Load
– Skript, DBUnit, …
• Manuell– Prod Extract, …
• Anwendungs-API– EntityManager, XyzRepository
<waehrung id="USD"> …
>import 2013-11-07.dump
dirk.weil@gedoplan.deFeige sein!12 dirk.weil@gedoplan.de
Testdaten-Bereitstellung• Daten vor dem Test löschen …
– höhere Komponenten zuerst• … und neu laden
– niedere Komponenten zuerst• Daten nach Test stehen lassen!
• Lässt sich gut mit CDI implementieren
dirk.weil@gedoplan.deFeige sein!13 dirk.weil@gedoplan.de
Integration Tests• Test in Java EE Server• Test von Komponenten
inkl. der davon genutzten Schichten• Zugriff auf alle Java-EE-Ressourcen
– „echte“ Persistence Unit (mit Test-DB)– „echter“ Transaction Manager
• Toolset: JUnit, Arquillian, EE Server
dirk.weil@gedoplan.deFeige sein!14 dirk.weil@gedoplan.de
Arquillian• Server Lifecycle (Start/Stop)• Erstellung von Deployment Archives• Deployment (+Undeployment)• Integration mit JUnit und TestNG• Testausführung
– Server: White Box Test– Client: Black Box Test
• Diverse Erweiterungen
dirk.weil@gedoplan.de
Arquillian
Feige sein!15
Server starten Archiv erstellen und deployen
Tests durchführen
Archiv undeployen
Server stoppenweitere
Testklasse?
Remote ModeManaged Mode
dirk.weil@gedoplan.dedirk.weil@gedoplan.de
Arquillian• Container-Wahl durch Classpath
– verfügbare Container: https://docs.jboss.org/author/display/ARQ/Container+adapters
<dependency> <groupId>org.jboss.arquillian.junit</groupId> <artifactId>arquillian-junit-container</artifactId> <scope>test</scope></dependency>
<profiles> <profile> <id>astest_wildfly-8.0-managed</id> <dependencies> <dependency> <groupId>org.wildfly</groupId> <artifactId>wildfly-arquillian-container-managed</artifactId> <scope>test</scope> </dependency>
dirk.weil@gedoplan.deFeige sein!17 dirk.weil@gedoplan.de
Arquillian• JUnit Testrunner• Deployment mit ShrinkWrap erstellen
– neuen Archivnamen nutzen (z. B. UUID)– richtige Endung!
@RunWith(Arquillian.class)public class WaehrungServiceIntegrationTest{ @Deployment public static WebArchive createDeployment() { WebArchive archive = ShrinkWrap.create(WebArchive.class, deploymentUnitName + ".war"); archive.addClasses(…); archive.addAsWebInfResource(…); archive.addAsResource(…); archive.addAsLibraries(…);
dirk.weil@gedoplan.deFeige sein!18 dirk.weil@gedoplan.de
Arquillian• White Box Test
– @Deployment(testable=true) (Default)– Testklasse wird mit deployt– @Inject etc. nutzbar
@RunWith(Arquillian.class)public class WaehrungServiceIntegrationTest{ … @Inject WaehrungService waehrungService;
@Test public void testUmrechnenUSD() { … BigDecimal actual = this.waehrungService.umrechnen(fremdBetrag, fremdWaehrungId); Assert.assertEquals("Euro-Betrag", expected, actual);
dirk.weil@gedoplan.deFeige sein!19 dirk.weil@gedoplan.de
Arquillian• White Box Test
• Ausgenutzte Goodies– Passend erstelltes Deployment– angepasste PU-Definition
WaehrungRepository
WaehrungServiceWaehrung
EntityManager / PU TX Manager
dirk.weil@gedoplan.deFeige sein!20 dirk.weil@gedoplan.de
Arquillian• Black Box Test
– @Deployment(testable=false)– Test läuft im Client (IDE, Maven, etc.)– Zugriff nur Remote
@RunWith(Arquillian.class)public class WaehrungServiceRemoteIntegrationTest{ @Deployment(testable = false) public static WebArchive createDeployment() {
@RunWith(Arquillian.class)public class WaehrungRestServiceIntegrationTest{ @Deployment(testable = false) public static WebArchive createDeployment() {
dirk.weil@gedoplan.deFeige sein!21 dirk.weil@gedoplan.de
Arquillian• Black Box Test
– Remote EJB• Benötigt Client Lib des Servers• Service Locator
@RunWith(Arquillian.class)public class WaehrungServiceRemoteIntegrationTest{ … @Test public void testUmrechnenUSD() { … WaehrungServiceRemote waehrungService ‚ = ServiceLocator.getEjb(WaehrungServiceRemote.class, …); BigDecimal actual = waehrungService.umrechnen(fremdBetrag, fremdWaehrungId);
Assert.assertEquals("Euro-Betrag", expected, actual);
dirk.weil@gedoplan.deFeige sein!22 dirk.weil@gedoplan.de
Arquillian• Black Box Test
– REST Service• JAX-RS 2.0 / Java EE 7: Client API
@RunWith(Arquillian.class)public class WaehrungServiceRemoteIntegrationTest{ … @Test public void testUmrechnenUSD() { …
Client client = ClientBuilder.newClient(); WebTarget target = client.target(serverUrlWebContext + …); BigDecimal actual = target.request(MediaType.TEXT_PLAIN).get(BigDecimal.class);
Assert.assertEquals("Euro-Betrag", expected, actual);
dirk.weil@gedoplan.deFeige sein!23 dirk.weil@gedoplan.de
Drone• Arquillian-Erweiterung für Selenium• Browser-Fernsteuerung
– Drone übernimmt Lifecycle-Steuerung des dazu nötigen Selenium-Servers
– @Drone injiziert WebDriver (=Fernsteuerung)
– Browser wählbar via arquillian.xml• Firefox, Crome, IE, HtmlUnit, PhantomJS, …• häufig per Maven-Profil
dirk.weil@gedoplan.de
Drone
Feige sein!24
WaehrungRepository
WaehrungService
WaehrungModel+ Views
EntityManager / PU TX Manager
Waehrung
dirk.weil@gedoplan.de
Drone
Feige sein!25
@RunWith(Arquillian.class)public class WaehrungGuiIntegrationTest{ … @Drone WebDriver webDriver;
@Test public void testUmrechnenUSD() { … this.webDriver.get(serverUrlWebContext + "/demo/waehrungsrechner.xhtml");
WebElement fremdBetragField = this.webDriver.findElement(By.id("form:fremdBetrag")); fremdBetragField.clear(); fremdBetragField.sendKeys(fremdBetrag.toString()); … WebElement umrechnenButton = this.webDriver.findElement(By.id("form:umrechnen")); umrechnenButton.click();
WebElement euroBetragField = this.webDriver.findElement(By.id("form:euroBetrag")); String actual = euroBetragField.getText();
Assert.assertEquals("Eurowert", expected, actual);
dirk.weil@gedoplan.deFeige sein!26 dirk.weil@gedoplan.de
Drone• Grey Box Test
– Web GUI Fernbedienung wie zuvor– Abfrage des serverseitigen Zustands
• z. B. mittels Remote EJB@RunWith(Arquillian.class)public class ShopGuiIntegrationTest{ @Test public void testCreateBestellung() { … this.webDriver.get(serverUrlWebContext + "/demo/waehrungsrechner.xhtml"); … ShopGuiIntegrationTestInspectorRemote inspector = ServiceLocator.getEjb(ShopGuiIntegrationTestInspectorRemote.class, …); Assert.assertTrue("Bestellung nicht gespeichert", inspector.checkBestellungExists(expected));
dirk.weil@gedoplan.de
Arquillian Extensions
Feige sein!27
Persistence Initialisierung, Validierung und Cleanup der Datenbank
JaCoCo Code Coverage Monitoring
Performance Prüfung der Ausführungszeit
Warp Grey Box Testing mit Drone
Graphene Selenium-Erweiterung u. a. mit AJAX-Unterstützung und JQuery-Selektion
…
dirk.weil@gedoplan.deFeige sein!28 dirk.weil@gedoplan.de
Arquillian Experience• Mächtiges Werkzeug• Dokumentation je nach Extension sehr
gut bis nicht vorhanden• Aufwändige Konfiguration
– JAR-Hölle• Ausführungsgeschwindigkeit
dirk.weil@gedoplan.dedirk.weil@gedoplan.de
Links• Beispielprojekt
https://github.com/dirkweil/feige-sein• Arquillian
http://arquillian.org/• Arquillian Testing Guide
http://www.packtpub.com/arquillian-testing-guide/book
dirk.weil@gedoplan.deFeige sein!30 dirk.weil@gedoplan.de
Mehr Infos• Java-EE-Blog
http://javaeeblog.wordpress.com/• Expertenkreis Java
http://expertenkreisjava.blogspot.de• Schulung, Projektunterstützung etc.
dirk.weil@gedoplan.de
dirk.weil@gedoplan.de
Hrglymph
Schön, dass Sie da waren!
dirk.weil@gedoplan.de