Feige sein

Post on 28-Nov-2014

474 views 2 download

description

Vortrag auf der W-JAX München 2013

Transcript of Feige sein

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