Feige sein

32
Dirk Weil | GEDOPLAN GmbH Feige sein! Testen im EE-Umfeld

description

Vortrag auf der W-JAX München 2013

Transcript of Feige sein

Page 1: Feige sein

Dirk Weil | GEDOPLAN GmbH

Feige sein!Testen im EE-Umfeld

Page 2: Feige sein

[email protected]@gedoplan.de

Dirk Weil• GEDOPLAN GmbH, Bielefeld• Java EE seit 1998• Konzeption und

Realisierung• Vorträge• Seminare• Veröffentlichungen

2 Feige sein!

Page 3: Feige sein

[email protected]

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.

Page 4: Feige sein

[email protected]

Testen

Feige sein!4

Testen ist feige!

… dann lassen Sie uns feige sein!

Page 5: Feige sein

[email protected]@gedoplan.de

EE-Tests• Komplexe Komponenten-Landschaft• CDI / EJB

– @Inject, @Produces, @Alternative …• Plattform

– @PersistenceContext, @Transactional, …• Web

– @Named, @XyzScoped, @Path

Page 6: Feige sein

[email protected]

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

Page 7: Feige sein

[email protected]

Beispielprojekt

WaehrungRepository

WaehrungService

WaehrungModel+ Views

WaehrungRestService

BestellungRepository

ArtikelRepository

ShopModel+ Views

Artikel

Bestellung

Waehrung

Bestell-Position

EntityManager / PU TX Manager

Page 8: Feige sein

[email protected] sein!8 [email protected]

Unit Test• Test: Umrechnung in WaehrungService• Mock für WaehrungRepository• Toolset: JUnit, Mockito

WaehrungRepository

WaehrungServiceWaehrung

Page 9: Feige sein

[email protected] sein!9 [email protected]

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

Page 10: Feige sein

[email protected] sein!10 [email protected]

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

Page 11: Feige sein

[email protected] sein!11 [email protected]

Testdaten-Bereitstellung• Bulk Load

– Skript, DBUnit, …

• Manuell– Prod Extract, …

• Anwendungs-API– EntityManager, XyzRepository

<waehrung id="USD"> …

>import 2013-11-07.dump

Page 12: Feige sein

[email protected] sein!12 [email protected]

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

Page 13: Feige sein

[email protected] sein!13 [email protected]

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

Page 14: Feige sein

[email protected] sein!14 [email protected]

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

Page 15: Feige sein

[email protected]

Arquillian

Feige sein!15

Server starten Archiv erstellen und deployen

Tests durchführen

Archiv undeployen

Server stoppenweitere

Testklasse?

Remote ModeManaged Mode

Page 16: Feige sein

[email protected]@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>

Page 17: Feige sein

[email protected] sein!17 [email protected]

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(…);

Page 18: Feige sein

[email protected] sein!18 [email protected]

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);

Page 19: Feige sein

[email protected] sein!19 [email protected]

Arquillian• White Box Test

• Ausgenutzte Goodies– Passend erstelltes Deployment– angepasste PU-Definition

WaehrungRepository

WaehrungServiceWaehrung

EntityManager / PU TX Manager

Page 20: Feige sein

[email protected] sein!20 [email protected]

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() {

Page 21: Feige sein

[email protected] sein!21 [email protected]

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);

Page 22: Feige sein

[email protected] sein!22 [email protected]

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);

Page 23: Feige sein

[email protected] sein!23 [email protected]

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

Page 24: Feige sein

[email protected]

Drone

Feige sein!24

WaehrungRepository

WaehrungService

WaehrungModel+ Views

EntityManager / PU TX Manager

Waehrung

Page 25: Feige sein

[email protected]

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);

Page 26: Feige sein

[email protected] sein!26 [email protected]

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));

Page 27: Feige sein

[email protected]

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

Page 28: Feige sein

[email protected] sein!28 [email protected]

Arquillian Experience• Mächtiges Werkzeug• Dokumentation je nach Extension sehr

gut bis nicht vorhanden• Aufwändige Konfiguration

– JAR-Hölle• Ausführungsgeschwindigkeit

Page 29: Feige sein

[email protected]@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

Page 30: Feige sein

[email protected] sein!30 [email protected]

Mehr Infos• Java-EE-Blog

http://javaeeblog.wordpress.com/• Expertenkreis Java

http://expertenkreisjava.blogspot.de• Schulung, Projektunterstützung etc.

[email protected]

Page 31: Feige sein

[email protected]

Hrglymph

Page 32: Feige sein

Schön, dass Sie da waren!

[email protected]