2. Dirk Weil
GEDOPLAN GmbH, Bielefeld
Java EE seit 1998
Konzeption und
Realisierung
Vorträge
Seminare
Veröffentlichungen
2Feige sein!
3. Testen
3Feige 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.
6. realembedded
SE-Test
Was und wie schnell?
6Feige sein!
Ausführungszeit
Testtiefe
Unit
Test
Multi Unit
Test
Integration
Test
Einzelklasse Komponente
Subsystem
Anwendung
Service
(inkl. Umgebung)
In-Container-Test
8. Unit Test
Test: Umrechnung in WaehrungService
Mock für WaehrungRepository
Toolset: JUnit, Mockito
8Feige sein!
WaehrungRepository
WaehrungService
Waehrung
9. Unit Test
9Feige 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“
10. Multi Unit Test
Test: Umrechnung in WaehrungService
Test-DB statt Prod-DB
Toolset: JUnit, CDI-Container
alternativer Producer für EntityManager
TX-Interceptor
10Feige sein!
WaehrungRepository
WaehrungService
Waehrung
EntityManager / PU TX Manager
11. 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;
12. Multi Unit Test
Mocking – the CDI way
(1: Alternative)
12Feige 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
13. Multi Unit Test
Mocking – the CDI way
(2: Interceptor)
13Feige 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
15. 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)
15Feige sein!
16. 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
16Feige sein!
17. 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
17Feige sein!
18. 18Feige sein!
Arquillian
Server starten Archiv erstellen und deployen
Tests durchführen
Archiv undeployen
Server stoppen
weitere
Testklasse?
Remote ModeManaged Mode
20. Arquillian
JUnit Testrunner
Deployment mit ShrinkWrap erstellen
neuen Archivnamen nutzen (z. B. UUID)
richtige Endung!
20Feige 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(…);
21. Arquillian
White Box Test
@Deployment(testable=true) (Default)
Testklasse wird mit deployt
@Inject etc. nutzbar
21Feige 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);
22. Arquillian
White Box Test
Passend erstelltes Deployment
angepasste PU-Definition
22Feige sein!
WaehrungRepository
WaehrungService
Waehrung
EntityManager / PU TX Manager
23. Arquillian
White Box Test
23Feige 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
24. 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
24Feige 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()
{
25. Arquillian
Black Box Test
25Feige 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
26. 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
26Feige sein!
29. Drone
Grey Box Test
Web GUI Fernbedienung wie zuvor
Abfrage des serverseitigen Zustands
z. B. mittels Remote EJB
29Feige 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));
30. Arquillian Extensions
30Feige 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
…
33. 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/
dirk.weil@gedoplan.de
@dirkweil
34Feige sein! dirk.weil@gedoplan.de