Top Banner
Feige sein! Testen im EE-Umfeld Dirk Weil, GEDOPLAN GmbH
33

Feige sein! Testen im Java-EE-Umfeld

May 22, 2015

Download

Technology

gedoplan

GEDOPLAN-Vortrag zum Thema Unit Tests, Multi Unit Tests und Integration Tests insbesondere für Anwendungen auf Basis der Java EE. (www.gedoplan.de)
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Feige sein! Testen im Java-EE-Umfeld

Feige sein!

Testen im EE-Umfeld

Dirk Weil, GEDOPLAN GmbH

Page 2: Feige sein! Testen im Java-EE-Umfeld

Dirk Weil

GEDOPLAN GmbH, Bielefeld

Java EE seit 1998

Konzeption und

Realisierung

Vorträge

Seminare

Veröffentlichungen

2 Feige sein!

Page 3: Feige sein! Testen im Java-EE-Umfeld

Testen

3 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.

Page 4: Feige sein! Testen im Java-EE-Umfeld

Testen

4 Feige sein!

Testen ist feige!

… dann lassen Sie uns feige sein!

Page 5: Feige sein! Testen im Java-EE-Umfeld

EE-Tests

Komplexe Komponenten-Landschaft

CDI / EJB

@Inject, @Produces, @Alternative …

Plattform

@PersistenceContext, @Transactional, …

Web

@Named, @XyzScoped, @Path

5 Feige sein!

Page 6: Feige sein! Testen im Java-EE-Umfeld

real

embedded

SE-Test

Was und wie schnell?

6 Feige sein!

Ausf

ühru

ngsz

eit

Testtiefe

Unit

Test

Multi Unit

Test

Integration

Test

Einzelklasse Komponente

Subsystem

Anwendung

Service

(inkl. Umgebung)

In-Container-Test

Page 7: Feige sein! Testen im Java-EE-Umfeld

Beispielprojekt

7 Feige sein!

WaehrungRepository

WaehrungService

WaehrungModel

+ Views

WaehrungRestService

BestellungRepository

ArtikelRepository

ShopModel

+ Views

Artikel

Bestellung

Waehrung

Bestell-

Position

EntityManager / PU TX Manager

Page 8: Feige sein! Testen im Java-EE-Umfeld

Unit Test

Test: Umrechnung in WaehrungService

Mock für WaehrungRepository

Toolset: JUnit, Mockito

8 Feige sein!

WaehrungRepository

WaehrungService Waehrung

Page 9: Feige sein! Testen im Java-EE-Umfeld

Unit Test

9 Feige sein!

@Stateless @LocalBean

public class WaehrungService implements WaehrungServiceRemote

{

@Inject

WaehrungRepository waehrungRepository;

public BigDecimal getTauschkurs(String waehrungId)

{

Waehrung waehrung = waehrungRepository.findById(waehrungId);

public class WaehrungServiceUnitTest

{

@BeforeClass

public static void beforeClass()

{

repository = Mockito.mock(WaehrungRepository.class);

Mockito.when(repository.findById("USD")).thenReturn(USD);

service = new WaehrungService();

service.waehrungRepository = repository;

}

Mock-Objekt vorbereiten

„Injektion“

Page 10: Feige sein! Testen im Java-EE-Umfeld

Multi Unit Test

Test: Umrechnung in WaehrungService

Test-DB statt Prod-DB

Toolset: JUnit, CDI-Container

alternativer Producer für EntityManager

TX-Interceptor

10 Feige sein!

WaehrungRepository

WaehrungService Waehrung

EntityManager / PU TX Manager

Page 11: Feige sein! Testen im Java-EE-Umfeld

Multi Unit Test

Apache

DeltaSpike

Container-

Start

Kontext-

Start

Injektion

in unmanaged

Objects

public class WaehrungServiceMultiTest { private static CdiContainer cdiContainer; @BeforeClass public static void beforeClass() { cdiContainer = CdiContainerLoader.getCdiContainer(); cdiContainer.boot(); cdiContainer.getContextControl().startContexts(); } @Before public void before() { BeanProvider.injectFields(this); } @Inject WaehrungService waehrungService;

Page 12: Feige sein! Testen im Java-EE-Umfeld

Multi Unit Test

Mocking – the CDI way

(1: Alternative)

12 Feige sein!

public class EntityManagerProducer

{

@PersistenceContext(unitName = "seminar")

@Produces

private EntityManager entityManager;

} @Alternative @Priority(1)

public class TestEntityManagerProducer

{

EntityManagerFactory emf;

@PostConstruct

private void postConstruct()

{

emf= Persistence.createEntityManagerFactory("test");

}

@Produces

EntityManager createEntityManager()

{

return emf.createEntityManager();

Mock-Objekt

nur im

Test-Classpath

Page 13: Feige sein! Testen im Java-EE-Umfeld

Multi Unit Test

Mocking – the CDI way

(2: Interceptor)

13 Feige sein!

@Transactional

public class WaehrungRepository

{

public void persist(Waehrung entity)

{

this.entityManager.persist(entity);

@Interceptor @Priority(Interceptor.Priority.APPLICATION + 1)

@Transactional

public class TestTransactionInterceptor

{

@Inject

EntityManager entityManager;

@AroundInvoke

Object manageTX(InvocationContext invocationContext) throws Exception

{

this.entityManager.getTransaction().begin();

Mock-Objekt

nur im

Test-Classpath

Page 14: Feige sein! Testen im Java-EE-Umfeld

Testdaten-Bereitstellung

Bulk Load

Skript, DBUnit, …

Manuell

Prod Extract, …

Anwendungs-API

EntityManager, XyzRepository

14 Feige sein!

<waehrung

id="USD">

>import 2013-11-07.dump

Page 15: Feige sein! Testen im Java-EE-Umfeld

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

(Testdaten-Lader wiederum nur im Test-Classpath)

15 Feige sein!

Page 16: Feige sein! Testen im Java-EE-Umfeld

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

16 Feige sein!

Page 17: Feige sein! Testen im Java-EE-Umfeld

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

17 Feige sein!

Page 18: Feige sein! Testen im Java-EE-Umfeld

18 Feige sein!

Arquillian

Server starten Archiv erstellen und deployen

Tests durchführen

Archiv undeployen

Server stoppen weitere

Testklasse?

Remote Mode Managed Mode

Page 19: Feige sein! Testen im Java-EE-Umfeld

Arquillian

Container-Wahl durch Classpath

verfügbare Container:

https://docs.jboss.org/author/display/ARQ/Container+adapters

19 Feige sein!

<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 20: Feige sein! Testen im Java-EE-Umfeld

Arquillian

JUnit Testrunner

Deployment mit ShrinkWrap erstellen

neuen Archivnamen nutzen (z. B. UUID)

richtige Endung!

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

Page 21: Feige sein! Testen im Java-EE-Umfeld

Arquillian

White Box Test

@Deployment(testable=true) (Default)

Testklasse wird mit deployt

@Inject etc. nutzbar

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

Page 22: Feige sein! Testen im Java-EE-Umfeld

Arquillian

White Box Test

Passend erstelltes Deployment

angepasste PU-Definition

22 Feige sein!

WaehrungRepository

WaehrungService Waehrung

EntityManager / PU TX Manager

Page 23: Feige sein! Testen im Java-EE-Umfeld

Arquillian

White Box Test

23 Feige sein!

Archiv erstellen

- Benötigte Anwendungsdateien

- ggf. spezielle Testartefakte

(z.B. persistence.xml)

- Testklasse inkl. Dependencies

(automatisch per testable=true)

Testergebnisse einsammeln

Testlauf abschließen

Archiv deployen

Tests ausführen

Archiv undeployen

Client Server

Page 24: Feige sein! Testen im Java-EE-Umfeld

Arquillian

Black Box Test

@Deployment(testable=false)

Test läuft im Client

(IDE, Jenkins, etc.)

Zugriff nur Remote

z. B. EJB per Remoting

z. B. RESTful Service via JAX-RS Client

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

{

Page 25: Feige sein! Testen im Java-EE-Umfeld

Arquillian

Black Box Test

25 Feige sein!

Archiv erstellen

- Benötigte Anwendungsdateien

- ggf. spezielle Testartefakte

(z.B. persistence.xml)

Tests ausführen

Testlauf abschließen

Archiv deployen

Archiv undeployen

Client Server

remote

Page 26: Feige sein! Testen im Java-EE-Umfeld

Drone

Arquillian-Erweiterung für Selenium

Browser-Fernsteuerung

Drone übernimmt Lifecycle-Steuerung des ggf. nötigen Browsers

@Drone injiziert WebDriver (=Fernsteuerung)

Browser wählbar via arquillian.xml

Firefox, Crome, IE, HtmlUnit, PhantomJS, …

häufig per Maven-Profil

26 Feige sein!

Page 27: Feige sein! Testen im Java-EE-Umfeld

Drone

27 Feige sein!

WaehrungRepository

WaehrungService

WaehrungModel

+ Views

EntityManager / PU TX Manager

Waehrung

Page 28: Feige sein! Testen im Java-EE-Umfeld

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

Page 29: Feige sein! Testen im Java-EE-Umfeld

Drone

Grey Box Test

Web GUI Fernbedienung wie zuvor

Abfrage des serverseitigen Zustands

z. B. mittels Remote EJB

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

Page 30: Feige sein! Testen im Java-EE-Umfeld

Arquillian Extensions

30 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

Page 31: Feige sein! Testen im Java-EE-Umfeld

Arquillian Experience

Mächtiges Werkzeug

Dokumentation je nach Extension sehr gut bis nicht vorhanden

Aufwändige Konfiguration

JAR-Hölle

Ausführungsgeschwindigkeit

31 Feige sein!

Page 33: Feige sein! Testen im Java-EE-Umfeld

More

Seminare zum Thema, z. B.

Java Software Testing

http://www.gedoplan-it-training.de

http://www.gedoplan-it-consulting.de

http://javaeeblog.wordpress.com/

http://expertenkreisjava.blogspot.de/

[email protected]

@dirkweil

34 Feige sein! [email protected]