testen im ee-umfeld – seien sie feige!
DESCRIPTION
Vortrag auf dem Expertenkreis Java am 21.11.2013TRANSCRIPT
Feige sein!
Testen im EE-Umfeld
Expertenkreis Java
21.11.2013, GEDOPLAN
Dirk Weil, GEDOPLAN GmbH
Testen
2 Feige sein!
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.
Testen
3 Feige sein!
Testen ist feige!
… dann lassen Sie uns feige sein!
EE-Tests
Komplexe Komponenten-Landschaft
CDI / EJB
@Inject, @Produces, @Alternative …
Plattform
@PersistenceContext, @Transactional, …
Web
@Named, @XyzScoped, @Path
Feige sein! 4
real
embedded
SE-Test
Was und wie schnell?
5 Feige sein!
Ausf
ühru
ngsz
eit
Testtiefe
Unit
Test
Multi Unit
Test
Integration
Test
Einzelklasse Komponente
Subsystem
Anwendung
Service
(inkl. Umgebung)
In-Container-Test
Beispielprojekt
WaehrungRepository
WaehrungService
WaehrungModel
+ Views
WaehrungRestService
BestellungRepository
ArtikelRepository
ShopModel
+ Views
Artikel
Bestellung
Waehrung
Bestell-
Position
EntityManager / PU TX Manager
Feige sein! 6
Unit Test
Test: Umrechnung in WaehrungService
Mock für WaehrungRepository
Toolset: JUnit, Mockito
7 Feige sein!
WaehrungRepository
WaehrungService Waehrung
Multi Unit Test
Test: Umrechnung in WaehrungService
Test-DB statt Prod-DB
Toolset: JUnit, CDI-Container
alternativer Producer für EntityManager
TX-Interceptor
8 Feige sein!
WaehrungRepository
WaehrungService Waehrung
EntityManager / PU TX Manager
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
9 Feige sein!
Testdaten-Bereitstellung
Bulk Load
Skript, DBUnit, …
Manuell
Prod Extract, …
Anwendungs-API
EntityManager, XyzRepository
10 Feige sein!
<waehrung
id="USD">
…
>import 2013-11-07.dump
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
11 Feige sein!
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
12 Feige sein!
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
13 Feige sein!
14 Feige sein!
Arquillian
Server starten Archiv erstellen und deployen
Tests durchführen
Archiv undeployen
Server stoppen weitere
Testklasse?
Remote Mode Managed Mode
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>
Feige sein! 15
Arquillian
JUnit Testrunner
Deployment mit ShrinkWrap erstellen
neuen Archivnamen nutzen (z. B. UUID)
richtige Endung!
16 Feige sein!
@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(…);
Arquillian
White Box Test
@Deployment(testable=true) (Default)
Testklasse wird mit deployt
@Inject etc. nutzbar
17 Feige sein!
@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);
Arquillian
White Box Test
Ausgenutzte Goodies
Passend erstelltes Deployment
angepasste PU-Definition
18 Feige sein!
WaehrungRepository
WaehrungService Waehrung
EntityManager / PU TX Manager
Arquillian
Black Box Test
@Deployment(testable=false)
Test läuft im Client (IDE, Maven, etc.)
Zugriff nur Remote
19 Feige sein!
@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()
{
Arquillian
Black Box Test
Remote EJB
Benötigt Client Lib des Servers
Service Locator
20 Feige sein!
@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);
Arquillian
Black Box Test
REST Service
JAX-RS 2.0 / Java EE 7: Client API
21 Feige sein!
@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);
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
22 Feige sein!
Drone
23 Feige sein!
WaehrungRepository
WaehrungService
WaehrungModel
+ Views
EntityManager / PU TX Manager
Waehrung
24 Feige sein!
Drone
@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);
Drone
Grey Box Test
Web GUI Fernbedienung wie zuvor
Abfrage des serverseitigen Zustands
z. B. mittels Remote EJB
25 Feige sein!
@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));
Arquillian Extensions
26 Feige sein!
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
…
Arquillian Experience
Mächtiges Werkzeug
Dokumentation je nach Extension sehr gut bis nicht vorhanden
Aufwändige Konfiguration
JAR-Hölle
Ausführungsgeschwindigkeit
27 Feige sein!
Links
Beispielprojekt
https://github.com/dirkweil/feige-sein
Arquillian
http://arquillian.org/
Arquillian Testing Guide
http://www.packtpub.com/arquillian-testing-guide/book
Feige sein! 28
Mehr Infos
Java-EE-Blog
http://javaeeblog.wordpress.com/
Expertenkreis Java
http://expertenkreisjava.blogspot.de
Schulung, Projektunterstützung etc.
29 Feige sein!
Hrglymph
30 Feige sein!
Schön, dass Sie da waren!
[email protected] Feige sein! 31