SlideShare ist ein Scribd-Unternehmen logo
— Drohnen und WARP-Antriebe —
JSF-Anwendungen mit
Arquillian Drone und
Arquillian WARP testen
Bernd M¨uller, JAX 2014, 15.5.2014 2/61
Agenda
Arquillian
Arquillian Drone
Arquillian WARP
Bernd M¨uller, JAX 2014, 15.5.2014 3/61
Vorstellung Referent
Prof. Informatik (Ostfalia, HS Braunschweig/Wolfenb¨uttel)
Buchautor (JSF, Seam, JPA, ...)
Mitglied EGs JSR 344 (JSF 2.2) und JSR 338 (JPA 2.1)
Gesch¨aftsf¨uhrer PMST GmbH
. . .
Bernd M¨uller, JAX 2014, 15.5.2014 4/61
Arquillian
Bernd M¨uller, JAX 2014, 15.5.2014 5/61
Arquillian in der Selbstdarstellung
Auszug aus http://www.arquillian.org/
So you can rule your code. Not the bugs.
No more mocks.
No more container lifecycle and deployment hassles.
Just real tests!
Bernd M¨uller, JAX 2014, 15.5.2014 6/61
Kurzbeschreibung Arquillian
JBoss’ Test-Framework f¨ur Tests im Container
Dazu JUnit oder TestNG als Test-Runner
Und Test-Enricher, um Tests im Container laufen zu lassen
Und ShrinkWrap als Werkzeug f¨urs Packaging/Deployment
Prinzipieller Ablauf:
Test wird auf Client gepackt
Test und Laufzeiterweiterung wird im Container deployt
Test wird ausgef¨uhrt
Testergebnisse werden an Client zur¨uckgegeben
Test wird undeployt
Aktuell: Arquillian Core Version 1.1.4.Final, 31.3.2014
Bernd M¨uller, JAX 2014, 15.5.2014 7/61
Kurzbeschreibung Arquillian
JBoss’ Test-Framework f¨ur Tests im Container
Dazu JUnit oder TestNG als Test-Runner
Und Test-Enricher, um Tests im Container laufen zu lassen
Und ShrinkWrap als Werkzeug f¨urs Packaging/Deployment
Prinzipieller Ablauf:
Test wird auf Client gepackt
Test und Laufzeiterweiterung wird im Container deployt
Test wird ausgef¨uhrt
Testergebnisse werden an Client zur¨uckgegeben
Test wird undeployt
Aktuell: Arquillian Core Version 1.1.4.Final, 31.3.2014
Bernd M¨uller, JAX 2014, 15.5.2014 7/61
Kurzbeschreibung Arquillian
JBoss’ Test-Framework f¨ur Tests im Container
Dazu JUnit oder TestNG als Test-Runner
Und Test-Enricher, um Tests im Container laufen zu lassen
Und ShrinkWrap als Werkzeug f¨urs Packaging/Deployment
Prinzipieller Ablauf:
Test wird auf Client gepackt
Test und Laufzeiterweiterung wird im Container deployt
Test wird ausgef¨uhrt
Testergebnisse werden an Client zur¨uckgegeben
Test wird undeployt
Aktuell: Arquillian Core Version 1.1.4.Final, 31.3.2014
Bernd M¨uller, JAX 2014, 15.5.2014 7/61
Container, Deployments, Protokolle, Adapter
3 Betriebsmodi
Embedded Container
Managed Container
Remote Container
Protokolle
Local (embedded)
Servlet 2.5 / 3.0
JMX (nur JBoss)
Container-Adapter
JBoss-AS 4,5,6,7,8
Tomcat, Jetty
GlassFish
WebLogic
WebSphere
Im Zweifel: googeln und ausprobieren
Bernd M¨uller, JAX 2014, 15.5.2014 8/61
Container, Deployments, Protokolle, Adapter
3 Betriebsmodi
Embedded Container
Managed Container
Remote Container
Protokolle
Local (embedded)
Servlet 2.5 / 3.0
JMX (nur JBoss)
Container-Adapter
JBoss-AS 4,5,6,7,8
Tomcat, Jetty
GlassFish
WebLogic
WebSphere
Im Zweifel: googeln und ausprobieren
Bernd M¨uller, JAX 2014, 15.5.2014 8/61
Container, Deployments, Protokolle, Adapter
3 Betriebsmodi
Embedded Container
Managed Container
Remote Container
Protokolle
Local (embedded)
Servlet 2.5 / 3.0
JMX (nur JBoss)
Container-Adapter
JBoss-AS 4,5,6,7,8
Tomcat, Jetty
GlassFish
WebLogic
WebSphere
Im Zweifel: googeln und ausprobieren
Bernd M¨uller, JAX 2014, 15.5.2014 8/61
Beispiel: Test-Runner und Deployment
@RunWith(Arquillian.class)
public class CustomerServiceTest {
@Deployment
public static Archive <?> createTestArchive () {
return ShrinkWrap.create(WebArchive.class , "test.war")
.addClasses(Customer.class , CustomerService .class)
.addAsResource("META -INF/persistence.xml")
. addAsWebInfResource (
new File("src/main/webapp/WEB -INF/beans.xml"));
}
...
Bernd M¨uller, JAX 2014, 15.5.2014 9/61
Beispiel: Test-Runner und Deployment
@RunWith(Arquillian.class)
public class CustomerServiceTest {
@Deployment
public static Archive <?> createTestArchive () {
return ShrinkWrap.create(WebArchive.class , "test.war")
.addClasses(Customer.class , CustomerService .class)
.addAsResource("META -INF/persistence.xml")
. addAsWebInfResource (
new File("src/main/webapp/WEB -INF/beans.xml"));
}
...
Bernd M¨uller, JAX 2014, 15.5.2014 9/61
ShrinkWrap
Werkzeug zur Erstellung/Manipulation von Java-Archiven
(JARs, WARs, EARs)
Fr¨uher eigenst¨andiges JBoss-Projekt, jetzt
Arquillian-Teilprojekt
Fluent-API zum Erstellen eines Archives,
f¨ur sogenannte Micro Deployment,
im Beispiel zwei Klassen und Deployment-Descriptoren
Bernd M¨uller, JAX 2014, 15.5.2014 10/61
Verbesserungspotenzial
@Deployment
public static Archive <?> createTestArchive () {
return ShrinkWrap.create(WebArchive.class ,
generatedName)
.addPackage(true , Customer.class.getPackage ())
.addAsResource("META -INF/test -persistence.xml",
"META -INF/persistence.xml")
. addAsWebInfResource (EmptyAsset.INSTANCE , "beans.xml");
}
Generierter Deployment-Name
Ganzes Package, optional mit Sub-Packages
Spezieller Deployment-Descriptor f¨ur Test (JPA, CDI, . . . )
Leerer Deployment-Descriptor, auch String-Asset
Bernd M¨uller, JAX 2014, 15.5.2014 11/61
Verbesserungspotenzial
@Deployment
public static Archive <?> createTestArchive () {
return ShrinkWrap.create(WebArchive.class ,
generatedName)
.addPackage(true , Customer.class.getPackage ())
.addAsResource("META -INF/test -persistence.xml",
"META -INF/persistence.xml")
. addAsWebInfResource (EmptyAsset.INSTANCE , "beans.xml");
}
Generierter Deployment-Name
Ganzes Package, optional mit Sub-Packages
Spezieller Deployment-Descriptor f¨ur Test (JPA, CDI, . . . )
Leerer Deployment-Descriptor, auch String-Asset
Bernd M¨uller, JAX 2014, 15.5.2014 11/61
Verbesserungspotenzial
@Deployment
public static Archive <?> createTestArchive () {
return ShrinkWrap.create(WebArchive.class ,
generatedName)
.addPackage(true , Customer.class.getPackage ())
.addAsResource("META -INF/test -persistence.xml",
"META -INF/persistence.xml")
. addAsWebInfResource (EmptyAsset.INSTANCE , "beans.xml");
}
Generierter Deployment-Name
Ganzes Package, optional mit Sub-Packages
Spezieller Deployment-Descriptor f¨ur Test (JPA, CDI, . . . )
Leerer Deployment-Descriptor, auch String-Asset
Bernd M¨uller, JAX 2014, 15.5.2014 11/61
Verbesserungspotenzial
@Deployment
public static Archive <?> createTestArchive () {
return ShrinkWrap.create(WebArchive.class ,
generatedName)
.addPackage(true , Customer.class.getPackage ())
.addAsResource("META -INF/test -persistence.xml",
"META -INF/persistence.xml")
. addAsWebInfResource (EmptyAsset.INSTANCE , "beans.xml");
}
Generierter Deployment-Name
Ganzes Package, optional mit Sub-Packages
Spezieller Deployment-Descriptor f¨ur Test (JPA, CDI, . . . )
Leerer Deployment-Descriptor, auch String-Asset
Bernd M¨uller, JAX 2014, 15.5.2014 11/61
Verbesserungspotenzial
@Deployment
public static Archive <?> createTestArchive () {
return ShrinkWrap.create(WebArchive.class ,
generatedName)
.addPackage(true , Customer.class.getPackage ())
.addAsResource("META -INF/test -persistence.xml",
"META -INF/persistence.xml")
. addAsWebInfResource (EmptyAsset.INSTANCE , "beans.xml");
}
Generierter Deployment-Name
Ganzes Package, optional mit Sub-Packages
Spezieller Deployment-Descriptor f¨ur Test (JPA, CDI, . . . )
Leerer Deployment-Descriptor, auch String-Asset
Bernd M¨uller, JAX 2014, 15.5.2014 11/61
Beispiel: Zu testende EJB
@Stateless
public class CustomerService {
@PersistenceContext
EntityManager em;
public void persist(Customer customer) {
em.persist(customer );
}
public long getNumberOfCustomers () {
return em. createNamedQuery (
"Customer. getNumberOfCustomers ",
Long.class ). getSingleResult ();
}
}
Bernd M¨uller, JAX 2014, 15.5.2014 12/61
Beispiel: Der Test
@RunWith(Arquillian.class)
public class CustomerServiceTest {
@Deployment
public static Archive <?> createTestArchive () { ...}
@Inject
CustomerService customerService ;
@Test
public void testPersist () {
Customer customer = new Customer("Firstname", "Lastname"
assertNull(customer.getId ()); // ueberfluessig
customerService .persist(customer );
assertNotNull(customer.getId ());
}
Bernd M¨uller, JAX 2014, 15.5.2014 13/61
Beispiel: Alternativer Test
@Test
public void testPersist2 () {
Customer customer = new Customer("Firstname", "Lastname"
Long before = customerService . getNumberOfCustomers ();
customerService .persist(customer );
Long after= customerService . getNumberOfCustomers ();
assertTrue("Muss ein Customer mehr sein",
before + 1 == after );
}
Bernd M¨uller, JAX 2014, 15.5.2014 14/61
Beispiel: 3. Alternative mit Persistenzkontext
@RunWith(Arquillian.class)
public class CustomerServiceTest {
@PersistenceContext
EntityManager em;
@Test
public void testPersist3 () {
Customer customer = new Customer("Firstname", "Lastname"
Long before = em. createNamedQuery (
"Customer. getNumberOfCustomers ", Long.class)
. getSingleResult ();
customerService .persist(customer );
Long after= em. createNamedQuery (
"Customer. getNumberOfCustomers ", Long.class)
. getSingleResult ();
assertTrue("Muss ein Customer mehr sein",
before + 1 == after );
}
Beispiel: 3. Alternative mit Persistenzkontext
@RunWith(Arquillian.class)
public class CustomerServiceTest {
@PersistenceContext
EntityManager em;
@Test
public void testPersist3 () {
Customer customer = new Customer("Firstname", "Lastname"
Long before = em. createNamedQuery (
"Customer. getNumberOfCustomers ", Long.class)
. getSingleResult ();
customerService .persist(customer );
Long after= em. createNamedQuery (
"Customer. getNumberOfCustomers ", Long.class)
. getSingleResult ();
assertTrue("Muss ein Customer mehr sein",
before + 1 == after );
}
Existiert, da Test in Container
”
Richtige Anwendungen“: Multiple Deployments (Doku)
@Deployment(name = "dep1", order = 1)
public static WebArchive createDep1 () { ... }
@Deployment(name = "dep2", order = 2)
public static WebArchive createDep2 () { ... }
@Test @OperateOnDeployment ("dep1")
public void testRunningInDep1 () { ... }
@Test @OperateOnDeployment ("dep2")
public void testRunningInDep2 () { ... }
Bernd M¨uller, JAX 2014, 15.5.2014 16/61
Erweiterbarkeit
Wie alle modernen Systeme/Frameworks besitzt Arquillian ein
Service Provider Interface
Aktuelle Erweiterungen:
Drone (Web-UI)
WARP (JSF)
Persistence
Performance
Graphene (UI, AJAX)
Seam 2
Bernd M¨uller, JAX 2014, 15.5.2014 17/61
Arquillian Drone
Bernd M¨uller, JAX 2014, 15.5.2014 18/61
Arquillian Drone
Arquillian-Erweiterung f¨ur funktionale Tests
Basiert auf Selenium
Selenium-Slogan: Selenium automates browsers
WebDriver: M¨oglichkeit zur Browser-Steuerung, u.a. mit Java
API
WebDriver API das einzig neu zu lernende
¨Anderung des prinzipiellen Ablaufs: Tests auf Client
Kombination Client und Server m¨oglich
Version aktuell: 1.3.0.Final
Version 2.0.0.Alpha1 mit ¨uberarbeitetem/entschlacktem API
in Entwicklung (von uns nicht verwendet)
Bernd M¨uller, JAX 2014, 15.5.2014 19/61
Die n¨otigen Erweiterungen/¨Anderungen
@RunWith(Arquillian.class)
public class DroneUsedTest {
@ArquillianResource
URL deploymentURL;
@Drone
WebDriver driver;
@Deployment(testable = false)
public static Archive <?> createTestArchive () { ...}
@ArquillianResource: das URL des Deployments
@Drone: das WebDriver oder DefaultSelenium API
Keine Tests im Server
Bernd M¨uller, JAX 2014, 15.5.2014 20/61
Die n¨otigen Erweiterungen/¨Anderungen
@RunWith(Arquillian.class)
public class DroneUsedTest {
@ArquillianResource
URL deploymentURL;
@Drone
WebDriver driver;
@Deployment(testable = false)
public static Archive <?> createTestArchive () { ...}
@ArquillianResource: das URL des Deployments
@Drone: das WebDriver oder DefaultSelenium API
Keine Tests im Server
Bernd M¨uller, JAX 2014, 15.5.2014 20/61
Die n¨otigen Erweiterungen/¨Anderungen
@RunWith(Arquillian.class)
public class DroneUsedTest {
@ArquillianResource
URL deploymentURL;
@Drone
WebDriver driver;
@Deployment(testable = false)
public static Archive <?> createTestArchive () { ...}
@ArquillianResource: das URL des Deployments
@Drone: das WebDriver oder DefaultSelenium API
Keine Tests im Server
Bernd M¨uller, JAX 2014, 15.5.2014 20/61
Die n¨otigen Erweiterungen/¨Anderungen
@RunWith(Arquillian.class)
public class DroneUsedTest {
@ArquillianResource
URL deploymentURL;
@Drone
WebDriver driver;
@Deployment(testable = false)
public static Archive <?> createTestArchive () { ...}
@ArquillianResource: das URL des Deployments
@Drone: das WebDriver oder DefaultSelenium API
Keine Tests im Server
Bernd M¨uller, JAX 2014, 15.5.2014 20/61
Falls nicht nur Client-Tests
@RunWith(Arquillian.class)
public class DroneUsedTest {
@Drone
WebDriver driver;
@Deployment
public static Archive <?> createTestArchive () { ... }
@Test
@RunAsClient
@InSequence (1)
public void createCustomer( @ArquillianResource URL url) {
@Test // im Server
@InSequence (2)
public void countCustomers () { ... }
Auch Tests im Server m¨oglich, daher Unterscheidung
Reihenfolge der Tests (Widerspruch zur reinen Lehre?)
Falls nicht nur Client-Tests
@RunWith(Arquillian.class)
public class DroneUsedTest {
@Drone
WebDriver driver;
@Deployment
public static Archive <?> createTestArchive () { ... }
@Test
@RunAsClient
@InSequence (1)
public void createCustomer( @ArquillianResource URL url) {
@Test // im Server
@InSequence (2)
public void countCustomers () { ... }
Auch Tests im Server m¨oglich, daher Unterscheidung
Reihenfolge der Tests (Widerspruch zur reinen Lehre?)
Falls nicht nur Client-Tests
@RunWith(Arquillian.class)
public class DroneUsedTest {
@Drone
WebDriver driver;
@Deployment
public static Archive <?> createTestArchive () { ... }
@Test
@RunAsClient
@InSequence (1)
public void createCustomer( @ArquillianResource URL url) {
@Test // im Server
@InSequence (2)
public void countCustomers () { ... }
Auch Tests im Server m¨oglich, daher Unterscheidung
Reihenfolge der Tests (Widerspruch zur reinen Lehre?)
Versteht Arquillian Maven’s POM ?
Nein, aber ShrinkWrap
Es gibt einen ShrinkWrap-Resolver, der Maven und Gradle
unterst¨utzt
Jetzt Beispiel:
JSF-Seite zur Kundenneuanlage
Navigation zu Kundenanlage-Erfolgreich-Seite, falls kein Fehler
Test, ob Navigation funktioniert
Test, ob Daten im Server
Bernd M¨uller, JAX 2014, 15.5.2014 22/61
Versteht Arquillian Maven’s POM ?
Nein, aber ShrinkWrap
Es gibt einen ShrinkWrap-Resolver, der Maven und Gradle
unterst¨utzt
Jetzt Beispiel:
JSF-Seite zur Kundenneuanlage
Navigation zu Kundenanlage-Erfolgreich-Seite, falls kein Fehler
Test, ob Navigation funktioniert
Test, ob Daten im Server
Bernd M¨uller, JAX 2014, 15.5.2014 22/61
Das (fast) komplette Beispiel (Teil 1)
@RunWith(Arquillian.class)
public class CreateCustomerTest {
private static final String
WEBAPP_SRC = "src/main/webapp";
@Drone
WebDriver driver;
@Inject
CustomerRepository customerRepository ;
Bernd M¨uller, JAX 2014, 15.5.2014 23/61
Das (fast) komplette Beispiel (Teil 2)
@Deployment
public static Archive <?> createTestArchive () {
MavenDependencyResolver resolver =
DependencyResolvers .use( MavenDependencyResolver .class)
. loadMetadataFromPom ("pom.xml");
return ShrinkWrap.create(WebArchive.class , "test.war")
.addPackages (...). addClasses (...)
.addAsResource("META -INF/test -persistence.xml",
"META -INF/persistence.xml")
. addAsWebInfResource ("test -ds.xml")
. addAsWebResource (new File(WEBAPP_SRC ,
"create.xhtml"))
. addAsWebResource (new File(WEBAPP_SRC ,
"customer -created.xhtml"))
. addAsWebInfResource (EmptyAsset.INSTANCE , "beans.xml")
. addAsWebInfResource (
new StringAsset("<faces -config version ="2.0"/ >"),
"faces -config.xml")
.addAsLibraries (
resolver.artifact("org.seleniumhq.selenium:selenium -ja
. resolveAsFiles ());
}
Das (fast) komplette Beispiel (Teil 3)
@Test
@RunAsClient
@InSequence (1)
public void createCustomer( @ArquillianResource URL url) {
driver.get(url + "create.jsf");
driver.findElement(By.id("create:firstname"))
.sendKeys("firstname");
driver.findElement(By.id("create:lastname"))
.sendKeys("lastname");
driver.findElement(By.id("create:dob"))
.sendKeys("1.1.2000");
driver.findElement(By.id("create:email"))
.sendKeys("email");
driver.findElement(By.id("create:password"))
.sendKeys("password");
driver.findElement(By.id("create:create")). click ();
assertTrue(driver.findElement(
By.xpath("// body[contains(text(), ’Kunde angelegt ’)]"))
.isDisplayed ());
}
Das (fast) komplette Beispiel (Teil 4)
@Test // im Server
@InSequence (2)
public void countCustomers () {
assertEquals (1, customerRepository .getCustomers (). size ());
}
Bernd M¨uller, JAX 2014, 15.5.2014 26/61
@Drone im Detail
Injection in Klasse
Class-Based Life-Cycle
Analog zu @BeforeClass / @AfterClass
Injection in Methode
Method-based Life-Cycle
Analog zu @Before / @After
Mehrere Injektionen ¨uber Qualifier m¨oglich
Verschiedene Driver: WebDriver, FirefoxDriver, ChromeDriver,
InternetExplorerDriver, SafariDriver
Durch Selenium Unterst¨utzung von XPath-Ausdr¨ucken in
Test-Asserts
Bernd M¨uller, JAX 2014, 15.5.2014 27/61
@Drone im Detail
Injection in Klasse
Class-Based Life-Cycle
Analog zu @BeforeClass / @AfterClass
Injection in Methode
Method-based Life-Cycle
Analog zu @Before / @After
Mehrere Injektionen ¨uber Qualifier m¨oglich
Verschiedene Driver: WebDriver, FirefoxDriver, ChromeDriver,
InternetExplorerDriver, SafariDriver
Durch Selenium Unterst¨utzung von XPath-Ausdr¨ucken in
Test-Asserts
Bernd M¨uller, JAX 2014, 15.5.2014 27/61
@Drone im Detail
Injection in Klasse
Class-Based Life-Cycle
Analog zu @BeforeClass / @AfterClass
Injection in Methode
Method-based Life-Cycle
Analog zu @Before / @After
Mehrere Injektionen ¨uber Qualifier m¨oglich
Verschiedene Driver: WebDriver, FirefoxDriver, ChromeDriver,
InternetExplorerDriver, SafariDriver
Durch Selenium Unterst¨utzung von XPath-Ausdr¨ucken in
Test-Asserts
Bernd M¨uller, JAX 2014, 15.5.2014 27/61
@Drone im Detail
Injection in Klasse
Class-Based Life-Cycle
Analog zu @BeforeClass / @AfterClass
Injection in Methode
Method-based Life-Cycle
Analog zu @Before / @After
Mehrere Injektionen ¨uber Qualifier m¨oglich
Verschiedene Driver: WebDriver, FirefoxDriver, ChromeDriver,
InternetExplorerDriver, SafariDriver
Durch Selenium Unterst¨utzung von XPath-Ausdr¨ucken in
Test-Asserts
Bernd M¨uller, JAX 2014, 15.5.2014 27/61
@Drone im Detail
Injection in Klasse
Class-Based Life-Cycle
Analog zu @BeforeClass / @AfterClass
Injection in Methode
Method-based Life-Cycle
Analog zu @Before / @After
Mehrere Injektionen ¨uber Qualifier m¨oglich
Verschiedene Driver: WebDriver, FirefoxDriver, ChromeDriver,
InternetExplorerDriver, SafariDriver
Durch Selenium Unterst¨utzung von XPath-Ausdr¨ucken in
Test-Asserts
Bernd M¨uller, JAX 2014, 15.5.2014 27/61
Arquillian WARP
Bernd M¨uller, JAX 2014, 15.5.2014 28/61
Arquillian Warp
Client-seitige Tests mit Zusicherungen/Pr¨ufung von
Server-seitiger Logik und Zustand
Keine weiteren Bibliotheken, wie etwa Selenium, ben¨otigt
Kein UI ben¨otigt (Headless)
Speziell f¨ur Servlets und Servlet-basierte Systeme gemacht
Im Augenblick nur Servlets direkt und JSF 2 unterst¨utzt
Arquillian Spring Framework Extension enth¨alt Warp Spring
MVC Extension (nicht betrachtet)
Offizieller Nachfolger von JSFUnit
Aktuell: Version 1.0.0.Alpha7, 11.3.2014
Bernd M¨uller, JAX 2014, 15.5.2014 29/61
Die prinzipielle Idee hinter WARP
Initiierung eines HTTP-Requests auf Client-Seite z.B. mit
WebDriver
Im selben Request-Zyklus Ausf¨uhren von Server-seitigen Tests
im Container
Dazu:
Initiieren des Request ¨uber Interface Activity
Inspizieren des Server-Zustands ¨uber Klasse Inspection
Aktivity mit perform()-Methode
Inspection mit JUnit/TestNG-Tests zum
”
richtigen“ Zeitpunkt
optional: Gruppieren und Observieren von Requests
Bernd M¨uller, JAX 2014, 15.5.2014 30/61
Die n¨otigen Erweiterungen/¨Anderungen
@WarpTest f¨ur Test-Klasse
@RunAsClient f¨ur Test-Klasse
@BeforeServlet, @AfterServlet f¨ur Servlet-Tests
@BeforePhase, @AfterPhase (6 Phasen) f¨ur JSF-Tests
Im Folgenden 3 Beispiele
Existieren die richtigen Beans?
Validierung
Navigation
Bernd M¨uller, JAX 2014, 15.5.2014 31/61
Die n¨otigen Erweiterungen/¨Anderungen
@WarpTest f¨ur Test-Klasse
@RunAsClient f¨ur Test-Klasse
@BeforeServlet, @AfterServlet f¨ur Servlet-Tests
@BeforePhase, @AfterPhase (6 Phasen) f¨ur JSF-Tests
Im Folgenden 3 Beispiele
Existieren die richtigen Beans?
Validierung
Navigation
Bernd M¨uller, JAX 2014, 15.5.2014 31/61
Die n¨otigen Erweiterungen/¨Anderungen
@WarpTest f¨ur Test-Klasse
@RunAsClient f¨ur Test-Klasse
@BeforeServlet, @AfterServlet f¨ur Servlet-Tests
@BeforePhase, @AfterPhase (6 Phasen) f¨ur JSF-Tests
Im Folgenden 3 Beispiele
Existieren die richtigen Beans?
Validierung
Navigation
Bernd M¨uller, JAX 2014, 15.5.2014 31/61
Die n¨otigen Erweiterungen/¨Anderungen
@WarpTest f¨ur Test-Klasse
@RunAsClient f¨ur Test-Klasse
@BeforeServlet, @AfterServlet f¨ur Servlet-Tests
@BeforePhase, @AfterPhase (6 Phasen) f¨ur JSF-Tests
Im Folgenden 3 Beispiele
Existieren die richtigen Beans?
Validierung
Navigation
Bernd M¨uller, JAX 2014, 15.5.2014 31/61
1. Beispiel: Existieren die richtigen Beans?
Weld-Manual: Einloggen ¨uber JSF-View-Bean
Pr¨ufen auf Benutzername/Passwort ¨uber EJB
CDI-produzierte Customer-Instanz im Session-Scope
Die Existenz dieser Instanz soll ¨uberpr¨uft werden
Bernd M¨uller, JAX 2014, 15.5.2014 32/61
JSF Login-Bean
@Named
@SessionScoped
public class Login implements Serializable {
@Inject
Credentials credentials;
@Inject
CustomerService customerService ;
private Customer loggedInCustomer ;
...
Bernd M¨uller, JAX 2014, 15.5.2014 33/61
JSF Login-Bean (cont’d)
public void login () {
loggedInCustomer = customerService .getCustomer (...
if ( loggedInCustomer == null) {
FacesMessage message = new FacesMessage("Falsche ...");
FacesContext. getCurrentInstance (). addMessage (...);
}
}
@Produces @LoggedIn
Customer getloggedInCustomer () {
return loggedInCustomer ;
}
public void logout () {
loggedInCustomer = null;
}
Bernd M¨uller, JAX 2014, 15.5.2014 34/61
Logged-In-Test
@RunWith(Arquillian.class)
@WarpTest
@RunAsClient
public class LoggedInTest {
@Deployment
public static Archive <?> createTestArchive () {
// nichts besonderes
}
@ArquillianResource
URL contextPath;
@Drone
WebDriver browser;
Bernd M¨uller, JAX 2014, 15.5.2014 35/61
Logged-In-Test (cont’d)
@Test
public void testLoggedIn () {
browser.navigate ().to(contextPath + "login.jsf");
browser.findElement(By.id("form:email")). sendKeys(EMAIL );
browser.findElement(By.id("form:password")). sendKeys(PASSW
Warp
.initiate(new Activity () {
public void perform () {
browser.findElement(By.id("form:login")). click ();
}})
.inspect(new Inspection () {
private static final long serialVersionUID = 1L;
@Inject
@LoggedIn
Customer customer;
Bernd M¨uller, JAX 2014, 15.5.2014 36/61
Struktur zur Verdeutlichung
Warp
.initiate(new Activity () {
...
})
.inspect(new Inspection () {
...
})
Aktivit¨at auf dem Client initiieren
Inspektion auf dem Server ausf¨uhren
Bernd M¨uller, JAX 2014, 15.5.2014 37/61
Logged-In-Test (cont’d)
Warp
.initiate(new Activity () {...} )
.inspect(new Inspection () {
private static final long serialVersionUID = 1L;
@Inject
@LoggedIn
Customer customer;
@BeforePhase(Phase. INVOKE_APPLICATION )
public void noCustomerExists () {
Assert.assertNull(
"LoggedIn Customer darf nicht existieren",
customer );
}
...
Bernd M¨uller, JAX 2014, 15.5.2014 38/61
Logged-In-Test (cont’d)
@BeforePhase(Phase. INVOKE_APPLICATION )
public void noCustomerExists () {
Assert.assertNull(
"LoggedIn Customer darf nicht existieren",
customer );
}
@AfterPhase(Phase. INVOKE_APPLICATION )
public void loggedInCustomerExists () {
Assert.assertNotNull(
"LoggedIn Customer muss existieren",
customer );
Assert.assertEquals("Falsche E-Mail",
EMAIL , customer.getEmail ());
Assert.assertEquals("Falsches Passwort",
PASSWORD , customer.getPassword ());
}
Bernd M¨uller, JAX 2014, 15.5.2014 39/61
Logged-In-Test (cont’d)
@BeforePhase(Phase. INVOKE_APPLICATION )
public void noCustomerExists () {
Assert.assertNull(
"LoggedIn Customer darf nicht existieren",
customer );
}
@AfterPhase(Phase. INVOKE_APPLICATION )
public void loggedInCustomerExists () {
Assert.assertNotNull(
"LoggedIn Customer muss existieren",
customer );
Assert.assertEquals("Falsche E-Mail",
EMAIL , customer.getEmail ());
Assert.assertEquals("Falsches Passwort",
PASSWORD , customer.getPassword ());
}
Bernd M¨uller, JAX 2014, 15.5.2014 39/61
Logged-In-Test (cont’d)
@BeforePhase(Phase. INVOKE_APPLICATION )
public void noCustomerExists () {
Assert.assertNull(
"LoggedIn Customer darf nicht existieren",
customer );
}
@AfterPhase(Phase. INVOKE_APPLICATION )
public void loggedInCustomerExists () {
Assert.assertNotNull(
"LoggedIn Customer muss existieren",
customer );
Assert.assertEquals("Falsche E-Mail",
EMAIL , customer.getEmail ());
Assert.assertEquals("Falsches Passwort",
PASSWORD , customer.getPassword ());
}
Bernd M¨uller, JAX 2014, 15.5.2014 39/61
2. Beispiel: Validierung
Credentials werden falsch eingegeben (zu kurz)
JSF erzeugt in Phase 3 FacesMessage-Instanzen
Pr¨ufen vor und nach Phase 3, ob Messages existieren oder
nicht
Bernd M¨uller, JAX 2014, 15.5.2014 40/61
Klasse Credentials
@Named
@RequestScoped
public class Credentials {
@NotNull
@Size(min = 6, max = 30)
private String email;
@NotNull
@Size(min = 6, max = 20)
private String password;
...
Deutsche Fehlermeldung f¨ur @Size: ”muss zwischen 6 ...
Bernd M¨uller, JAX 2014, 15.5.2014 41/61
Validierungstest
@RunWith(Arquillian.class)
@WarpTest
@RunAsClient
public class LoggedInValidationFailedTest {
// nichts besonderes im Deployment
@ArquillianResource
URL contextPath;
@Drone
WebDriver browser;
...
Bernd M¨uller, JAX 2014, 15.5.2014 42/61
Validierungstest (cont’d)
@Test
public void testValidation () {
browser.navigate ().to(contextPath + "login.jsf");
browser.findElement(By.id("form:email")). sendKeys("short")
browser.findElement(By.id("form:password")). sendKeys("shor
Warp
.initiate(new Activity () {
public void perform () {
browser.findElement(By.id("form:login")). click ();
}})
.inspect(new Inspection () {
private static final long serialVersionUID = 1L;
...
Bernd M¨uller, JAX 2014, 15.5.2014 43/61
Validierungstest (cont’d)
Warp
.initiate(new Activity () {...} )
.inspect(new Inspection () {
private static final long serialVersionUID = 1L;
@ArquillianResource
FacesContext facesContext;
@BeforePhase(Phase. PROCESS_VALIDATIONS )
public void noFacesMessage () {
Assert.assertEquals("Anzahl Fehler muss 0 sein",
0, facesContext.getMessageList (). size ());
}
...
Bernd M¨uller, JAX 2014, 15.5.2014 44/61
Validierungstest (cont’d)
Warp
.initiate(new Activity () {...} )
.inspect(new Inspection () {
private static final long serialVersionUID = 1L;
@ArquillianResource
FacesContext facesContext;
@BeforePhase(Phase. PROCESS_VALIDATIONS )
public void noFacesMessage () {
Assert.assertEquals("Anzahl Fehler muss 0 sein",
0, facesContext.getMessageList (). size ());
}
...
FacesContext injizierbar!
Bernd M¨uller, JAX 2014, 15.5.2014 44/61
Validierungstest (cont’d)
.inspect(new Inspection () {
...
@ArquillianResource
FacesContext facesContext;
@AfterPhase(Phase. PROCESS_VALIDATIONS )
public void facesMessagesExist () {
List <FacesMessage > messages =
facesContext.getMessageList ();
Assert.assertTrue(
facesContext.getMessageList (). size () != 0);
for (FacesMessage facesMessage : messages) {
Assert.assertTrue("Falsche Fehlermeldung",
facesMessage.getSummary ()
.startsWith("muss zwischen 6"));
}
}
Bernd M¨uller, JAX 2014, 15.5.2014 45/61
3. Beispiel: Navigation mit Redirect
Einfache JSF-Seiten mit Navigation und Redirect
Noch nicht erw¨ahntes WARP-Feature: Gruppieren von
Inspektionen auf Server basierend auf Request-Folge
Pr¨ufen der View-Id nach Restore-View-Phase
Bernd M¨uller, JAX 2014, 15.5.2014 46/61
JSF-Seiten mit Navigation
redirect-source.xhtml
<h:form id="form">
Seite verwendet #{ redirectSourceBean .name} <br />
<h:commandButton id="redirect"
action=" redirect-target ? faces-redirect=true"
value="Redirect to ’redirect-target .jsf ’" />
</h:form >
redirect-target.xhtml
<h:form id="form">
Seite verwendet #{ redirectTargetBean .name} />
</h:form >
Bernd M¨uller, JAX 2014, 15.5.2014 47/61
@RunWith(Arquillian.class)
@WarpTest
@RunAsClient
public class RedirectTest {
@Deployment
public static Archive <?> createTestArchive () {
return ShrinkWrap.create(WebArchive.class ,
"redirect -test.war")
...
. addAsWebResource (new File(WEBAPP_SRC ,
"redirect -source.xhtml"))
. addAsWebResource (new File(WEBAPP_SRC ,
"redirect -target.xhtml"))
...
}
@ArquillianResource URL contextPath;
@Drone WebDriver browser;
...
Bernd M¨uller, JAX 2014, 15.5.2014 48/61
Navigationstest (cont’d)
@Test
public void testRedirect () {
browser.navigate ().to(contextPath + "redirect -source.jsf")
Warp
.initiate(new Activity () {
public void perform () {
browser.findElement(By.id("form:redirect")). click ();
}})
.group("redirect -source.jsf")
.observe(HttpFilters.request (). index (1))
.inspect(new Inspection () {
private static final long serialVersionUID = 1L;
@AfterPhase(Phase.RESTORE_VIEW)
...
Bernd M¨uller, JAX 2014, 15.5.2014 49/61
Struktur zur Verdeutlichung
Warp
.initiate(new Activity () { ... }})
.group("redirect -source.jsf") // nur Doku
.observe(HttpFilters.request (). index (1))
.inspect(new Inspection () { ... })
.group("redirect -target.jsf") // nur Doku
.observe(HttpFilters.request (). index (2))
.inspect(new Inspection () { ... })
.execute ();
Assert.assertTrue(browser.getCurrentUrl ()
.contains("redirect -target.jsf"));
Bernd M¨uller, JAX 2014, 15.5.2014 50/61
Navigationstest (cont’d)
.group("redirect -source.jsf")
.observe(HttpFilters.request (). index (1))
.inspect(new Inspection () {
private static final long serialVersionUID = 1L;
@AfterPhase(Phase.RESTORE_VIEW)
public void verifyPage( @ArquillianResource
FacesContext facesContext) {
Assert.assertEquals("/redirect -source.xhtml",
facesContext.getViewRoot (). getViewId ());
}
})
Bernd M¨uller, JAX 2014, 15.5.2014 51/61
Navigationstest (cont’d)
.group("redirect -target.jsf")
.observe(HttpFilters.request (). index (2))
.inspect(new Inspection () {
private static final long serialVersionUID = 1L;
@AfterPhase(Phase.RESTORE_VIEW)
public void verifyPage( @ArquillianResource
FacesContext facesContext) {
Assert.assertEquals("/redirect -target.xhtml",
facesContext.getViewRoot (). getViewId ());
}
})
.execute ();
Assert.assertTrue(browser.getCurrentUrl ()
.contains("redirect -target.jsf"));
Bernd M¨uller, JAX 2014, 15.5.2014 52/61
Auswahl des richtigen Request
Da mehrere Request getriggert werden k¨onnen, muss man den
richtigen (den, den man observieren will) ausw¨ahlen
Dazu das HttpRequestFilter-Interface
Damit spezifiziert man den zu verwendenden HttpRequest der
aktuellen Gruppe
Bernd M¨uller, JAX 2014, 15.5.2014 53/61
Aus
”
Dokumentation“
import static org.jboss.arquillian.warp
.client.filter.http.HttpFilters.request;
// will accept only requests for HTML
... group ()
.observe(request (). uri (). contains(".html"))
// will accept only REST requests for JSON
... group ()
.observe(request (). header ()
.containsValue("Accept", "application/json"))
// will accept only POST requests
... group ()
.observe(request (). method (). equal(POST ))
Bernd M¨uller, JAX 2014, 15.5.2014 54/61
Was kann alles injiziert werden?
Injizierbar ¨uber @ArquillianResource
Servlet-Ressourcen
ServletRequest or HttpServletRequest
ServletResponse or HttpServletResponse
Bernd M¨uller, JAX 2014, 15.5.2014 55/61
Was kann alles injiziert werden? (cont’d)
Injizierbar ¨uber @ArquillianResource
JSF-Ressourcen
FacesContext
Application
ELContext, ELResolver, ExpressionFactory
ExceptionHandler
Flash
NavigationHandler
PartialViewContext
RenderKit
ResourceHandler
StateManager
UIViewRoot
ViewHandler
Bernd M¨uller, JAX 2014, 15.5.2014 56/61
Wo Licht ist, ist auch Schatten
Sehr schlechte Doku
Noch viele/schwere Fehler
Scheinbar Ein-Mann-Projekt: Luk´aˇs Fryˇc (Project Lead)
Bernd M¨uller, JAX 2014, 15.5.2014 57/61
Dokumentation WARP
Bernd M¨uller, JAX 2014, 15.5.2014 58/61
Zusammenfassung und (pers¨onliches) Fazit
Einerseits . . .
EAP Dokumentation enth¨alt kein Kapitel zu Arquillian
JBoss Dokumentation enh¨alt kein Kapitel zu WARP
Andererseits . . .
EAP Quickstarts enthalten Arquillian-Tests
JB225 Schulung enth¨alt Arquillian- und Drone-Tests
Arquillian und Erweiterungen sehr leistungsf¨ahig und
interessant
Mein Rat: fangen Sie an !
Bernd M¨uller, JAX 2014, 15.5.2014 59/61
Zusammenfassung und (pers¨onliches) Fazit
Einerseits . . .
EAP Dokumentation enth¨alt kein Kapitel zu Arquillian
JBoss Dokumentation enh¨alt kein Kapitel zu WARP
Andererseits . . .
EAP Quickstarts enthalten Arquillian-Tests
JB225 Schulung enth¨alt Arquillian- und Drone-Tests
Arquillian und Erweiterungen sehr leistungsf¨ahig und
interessant
Mein Rat: fangen Sie an !
Bernd M¨uller, JAX 2014, 15.5.2014 59/61
Zusammenfassung und (pers¨onliches) Fazit
Einerseits . . .
EAP Dokumentation enth¨alt kein Kapitel zu Arquillian
JBoss Dokumentation enh¨alt kein Kapitel zu WARP
Andererseits . . .
EAP Quickstarts enthalten Arquillian-Tests
JB225 Schulung enth¨alt Arquillian- und Drone-Tests
Arquillian und Erweiterungen sehr leistungsf¨ahig und
interessant
Mein Rat: fangen Sie an !
Bernd M¨uller, JAX 2014, 15.5.2014 59/61
Zusammenfassung und (pers¨onliches) Fazit
Einerseits . . .
EAP Dokumentation enth¨alt kein Kapitel zu Arquillian
JBoss Dokumentation enh¨alt kein Kapitel zu WARP
Andererseits . . .
EAP Quickstarts enthalten Arquillian-Tests
JB225 Schulung enth¨alt Arquillian- und Drone-Tests
Arquillian und Erweiterungen sehr leistungsf¨ahig und
interessant
Mein Rat: fangen Sie an !
Bernd M¨uller, JAX 2014, 15.5.2014 59/61
Referenzen
Arquillian Reference Guide
JSF Testing
John D. Ament. Arquillian Testing Guide. Packt Publishing,
2013.
Bernd M¨uller, JAX 2014, 15.5.2014 60/61
Fragen und Anmerkungen
Bernd M¨uller, JAX 2014, 15.5.2014 61/61

Weitere ähnliche Inhalte

Andere mochten auch

Arquillian
ArquillianArquillian
Arquillian
nukeevry1
 
Arquillian: Helping web developers and QA get along
Arquillian: Helping web developers and QA get alongArquillian: Helping web developers and QA get along
Arquillian: Helping web developers and QA get along
Lukáš Fryč
 
Page One Engine System
Page One Engine SystemPage One Engine System
Page One Engine System
psychoticautoma86
 
Vision & values poster
Vision & values posterVision & values poster
Vision & values poster
Megan White
 
Ga Trust Award Huntington Hall Rehab
Ga Trust Award Huntington Hall RehabGa Trust Award Huntington Hall Rehab
Ga Trust Award Huntington Hall RehabVincent Weaver
 
Dia del centre 2
Dia del centre 2Dia del centre 2
Dia del centre 2
IES Quarto de Portmany
 
CEC Danny Buccat - LOR for Massimo Muollo
CEC Danny Buccat - LOR for Massimo MuolloCEC Danny Buccat - LOR for Massimo Muollo
CEC Danny Buccat - LOR for Massimo MuolloMassimo Muollo
 
Comprehensive Assessment
Comprehensive AssessmentComprehensive Assessment
Comprehensive Assessment
Christopher Dirks, LMFT
 
Assessment of New Towns Self Sufficiency
Assessment of New Towns Self SufficiencyAssessment of New Towns Self Sufficiency
Assessment of New Towns Self Sufficiency
Jahanshah Pakzad
 
Can
CanCan
Um percurso pouco linear - Alexandre Costa
Um percurso pouco linear - Alexandre CostaUm percurso pouco linear - Alexandre Costa
Um percurso pouco linear - Alexandre CostaCláudio
 
информатика 589. компьютер
информатика 589. компьютеринформатика 589. компьютер
информатика 589. компьютер
Вячеслав Васильченко
 
GMNCV
GMNCVGMNCV

Andere mochten auch (20)

Arquillian
ArquillianArquillian
Arquillian
 
Arquillian: Helping web developers and QA get along
Arquillian: Helping web developers and QA get alongArquillian: Helping web developers and QA get along
Arquillian: Helping web developers and QA get along
 
Page One Engine System
Page One Engine SystemPage One Engine System
Page One Engine System
 
Fedr settore arredo
Fedr settore arredoFedr settore arredo
Fedr settore arredo
 
Raw Images
Raw ImagesRaw Images
Raw Images
 
MN evolució del web sexejoves
MN evolució del web sexejovesMN evolució del web sexejoves
MN evolució del web sexejoves
 
Untitled presentation
Untitled presentationUntitled presentation
Untitled presentation
 
Vision & values poster
Vision & values posterVision & values poster
Vision & values poster
 
Presentation1
Presentation1Presentation1
Presentation1
 
Ga Trust Award Huntington Hall Rehab
Ga Trust Award Huntington Hall RehabGa Trust Award Huntington Hall Rehab
Ga Trust Award Huntington Hall Rehab
 
Dia del centre 2
Dia del centre 2Dia del centre 2
Dia del centre 2
 
Reference Letter Zo mont
Reference Letter Zo montReference Letter Zo mont
Reference Letter Zo mont
 
Drac
DracDrac
Drac
 
CEC Danny Buccat - LOR for Massimo Muollo
CEC Danny Buccat - LOR for Massimo MuolloCEC Danny Buccat - LOR for Massimo Muollo
CEC Danny Buccat - LOR for Massimo Muollo
 
Comprehensive Assessment
Comprehensive AssessmentComprehensive Assessment
Comprehensive Assessment
 
Assessment of New Towns Self Sufficiency
Assessment of New Towns Self SufficiencyAssessment of New Towns Self Sufficiency
Assessment of New Towns Self Sufficiency
 
Can
CanCan
Can
 
Um percurso pouco linear - Alexandre Costa
Um percurso pouco linear - Alexandre CostaUm percurso pouco linear - Alexandre Costa
Um percurso pouco linear - Alexandre Costa
 
информатика 589. компьютер
информатика 589. компьютеринформатика 589. компьютер
информатика 589. компьютер
 
GMNCV
GMNCVGMNCV
GMNCV
 

Ähnlich wie Drohnen und WARP-Antriebe

Testing tools
Testing toolsTesting tools
Testing tools
Sebastian Springer
 
Best Practices für TDD in JavaScript
Best Practices für TDD in JavaScriptBest Practices für TDD in JavaScript
Best Practices für TDD in JavaScript
Sebastian Springer
 
BASTA 2016 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch...
BASTA 2016 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch...BASTA 2016 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch...
BASTA 2016 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch...
Marc Müller
 
Real Application Testing - DOAG SIG Database 2010 - Simon Dickmeiß
Real Application Testing - DOAG SIG Database 2010 - Simon DickmeißReal Application Testing - DOAG SIG Database 2010 - Simon Dickmeiß
Real Application Testing - DOAG SIG Database 2010 - Simon Dickmeiß
OPITZ CONSULTING Deutschland
 
Mögen die Tests mit dir sein
Mögen die Tests mit dir seinMögen die Tests mit dir sein
Mögen die Tests mit dir sein
codepitbull
 
A/B Testing mit Node.js
A/B Testing mit Node.jsA/B Testing mit Node.js
A/B Testing mit Node.js
Sebastian Springer
 
MicroProfile 2.x: Der alternative Standard
MicroProfile 2.x: Der alternative StandardMicroProfile 2.x: Der alternative Standard
MicroProfile 2.x: Der alternative Standard
OPEN KNOWLEDGE GmbH
 
Schnell, schneller, Quarkus!!
Schnell, schneller, Quarkus!!Schnell, schneller, Quarkus!!
Schnell, schneller, Quarkus!!
gedoplan
 
JFN 2017 - Instrumentierung - Das Werkzeug der Werkzeugmacher
JFN 2017 - Instrumentierung - Das Werkzeug der WerkzeugmacherJFN 2017 - Instrumentierung - Das Werkzeug der Werkzeugmacher
JFN 2017 - Instrumentierung - Das Werkzeug der Werkzeugmacher
berndmueller
 
2012-10-12 Testen mit Arquillian
2012-10-12 Testen mit Arquillian2012-10-12 Testen mit Arquillian
2012-10-12 Testen mit ArquillianMatthias Reining
 
Unit testing mit Javascript
Unit testing mit JavascriptUnit testing mit Javascript
Unit testing mit Javascript
joergreichert
 
Softwarequalitätssicherung mit Continuous Integration Tools
 Softwarequalitätssicherung mit Continuous Integration Tools Softwarequalitätssicherung mit Continuous Integration Tools
Softwarequalitätssicherung mit Continuous Integration Tools
gedoplan
 
AdvancedTdd
AdvancedTddAdvancedTdd
AdvancedTdd
jlink
 
Feige sein
Feige seinFeige sein
Feige sein
gedoplan
 
MicroProfile-Anwendungen mit Quarkus
MicroProfile-Anwendungen mit QuarkusMicroProfile-Anwendungen mit Quarkus
MicroProfile-Anwendungen mit Quarkus
gedoplan
 
JSF Testing - Tools und Technics
JSF Testing - Tools und TechnicsJSF Testing - Tools und Technics
JSF Testing - Tools und Technicsadesso AG
 
Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...
Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...
Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...
GFU Cyrus AG
 
Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10
Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10
Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10Ralf Sigmund
 
PHPUnit - Eine kurze Einführung
PHPUnit - Eine kurze EinführungPHPUnit - Eine kurze Einführung
PHPUnit - Eine kurze Einführung
frankstaude
 

Ähnlich wie Drohnen und WARP-Antriebe (20)

Testing tools
Testing toolsTesting tools
Testing tools
 
Best Practices für TDD in JavaScript
Best Practices für TDD in JavaScriptBest Practices für TDD in JavaScript
Best Practices für TDD in JavaScript
 
BASTA 2016 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch...
BASTA 2016 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch...BASTA 2016 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch...
BASTA 2016 - Alternativen zu Visual-Studio-Testtools: Wann lohnt es sich auch...
 
Real Application Testing - DOAG SIG Database 2010 - Simon Dickmeiß
Real Application Testing - DOAG SIG Database 2010 - Simon DickmeißReal Application Testing - DOAG SIG Database 2010 - Simon Dickmeiß
Real Application Testing - DOAG SIG Database 2010 - Simon Dickmeiß
 
Mögen die Tests mit dir sein
Mögen die Tests mit dir seinMögen die Tests mit dir sein
Mögen die Tests mit dir sein
 
A/B Testing mit Node.js
A/B Testing mit Node.jsA/B Testing mit Node.js
A/B Testing mit Node.js
 
MicroProfile 2.x: Der alternative Standard
MicroProfile 2.x: Der alternative StandardMicroProfile 2.x: Der alternative Standard
MicroProfile 2.x: Der alternative Standard
 
Schnell, schneller, Quarkus!!
Schnell, schneller, Quarkus!!Schnell, schneller, Quarkus!!
Schnell, schneller, Quarkus!!
 
JFN 2017 - Instrumentierung - Das Werkzeug der Werkzeugmacher
JFN 2017 - Instrumentierung - Das Werkzeug der WerkzeugmacherJFN 2017 - Instrumentierung - Das Werkzeug der Werkzeugmacher
JFN 2017 - Instrumentierung - Das Werkzeug der Werkzeugmacher
 
Automatisierungmit NANT
Automatisierungmit NANTAutomatisierungmit NANT
Automatisierungmit NANT
 
2012-10-12 Testen mit Arquillian
2012-10-12 Testen mit Arquillian2012-10-12 Testen mit Arquillian
2012-10-12 Testen mit Arquillian
 
Unit testing mit Javascript
Unit testing mit JavascriptUnit testing mit Javascript
Unit testing mit Javascript
 
Softwarequalitätssicherung mit Continuous Integration Tools
 Softwarequalitätssicherung mit Continuous Integration Tools Softwarequalitätssicherung mit Continuous Integration Tools
Softwarequalitätssicherung mit Continuous Integration Tools
 
AdvancedTdd
AdvancedTddAdvancedTdd
AdvancedTdd
 
Feige sein
Feige seinFeige sein
Feige sein
 
MicroProfile-Anwendungen mit Quarkus
MicroProfile-Anwendungen mit QuarkusMicroProfile-Anwendungen mit Quarkus
MicroProfile-Anwendungen mit Quarkus
 
JSF Testing - Tools und Technics
JSF Testing - Tools und TechnicsJSF Testing - Tools und Technics
JSF Testing - Tools und Technics
 
Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...
Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...
Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...
 
Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10
Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10
Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10
 
PHPUnit - Eine kurze Einführung
PHPUnit - Eine kurze EinführungPHPUnit - Eine kurze Einführung
PHPUnit - Eine kurze Einführung
 

Mehr von berndmueller

Compilers Everywhere
Compilers EverywhereCompilers Everywhere
Compilers Everywhere
berndmueller
 
Was jeder Java-Entwickler über Strings wissen sollte
Was jeder Java-Entwickler über Strings wissen sollteWas jeder Java-Entwickler über Strings wissen sollte
Was jeder Java-Entwickler über Strings wissen sollte
berndmueller
 
Hasta la vista Mandantenfähigkeit?
Hasta la vista Mandantenfähigkeit?Hasta la vista Mandantenfähigkeit?
Hasta la vista Mandantenfähigkeit?
berndmueller
 
Class Loading Revisited
Class Loading RevisitedClass Loading Revisited
Class Loading Revisited
berndmueller
 
Instrumentierung - Das Werkzeug der Werkzeugmacher -
Instrumentierung - Das Werkzeug der Werkzeugmacher - Instrumentierung - Das Werkzeug der Werkzeugmacher -
Instrumentierung - Das Werkzeug der Werkzeugmacher -
berndmueller
 
Was jeder Java-Entwickler über Strings wissen sollte
Was jeder Java-Entwickler über Strings wissen sollteWas jeder Java-Entwickler über Strings wissen sollte
Was jeder Java-Entwickler über Strings wissen sollte
berndmueller
 

Mehr von berndmueller (6)

Compilers Everywhere
Compilers EverywhereCompilers Everywhere
Compilers Everywhere
 
Was jeder Java-Entwickler über Strings wissen sollte
Was jeder Java-Entwickler über Strings wissen sollteWas jeder Java-Entwickler über Strings wissen sollte
Was jeder Java-Entwickler über Strings wissen sollte
 
Hasta la vista Mandantenfähigkeit?
Hasta la vista Mandantenfähigkeit?Hasta la vista Mandantenfähigkeit?
Hasta la vista Mandantenfähigkeit?
 
Class Loading Revisited
Class Loading RevisitedClass Loading Revisited
Class Loading Revisited
 
Instrumentierung - Das Werkzeug der Werkzeugmacher -
Instrumentierung - Das Werkzeug der Werkzeugmacher - Instrumentierung - Das Werkzeug der Werkzeugmacher -
Instrumentierung - Das Werkzeug der Werkzeugmacher -
 
Was jeder Java-Entwickler über Strings wissen sollte
Was jeder Java-Entwickler über Strings wissen sollteWas jeder Java-Entwickler über Strings wissen sollte
Was jeder Java-Entwickler über Strings wissen sollte
 

Drohnen und WARP-Antriebe

  • 1.
  • 2. — Drohnen und WARP-Antriebe — JSF-Anwendungen mit Arquillian Drone und Arquillian WARP testen Bernd M¨uller, JAX 2014, 15.5.2014 2/61
  • 3. Agenda Arquillian Arquillian Drone Arquillian WARP Bernd M¨uller, JAX 2014, 15.5.2014 3/61
  • 4. Vorstellung Referent Prof. Informatik (Ostfalia, HS Braunschweig/Wolfenb¨uttel) Buchautor (JSF, Seam, JPA, ...) Mitglied EGs JSR 344 (JSF 2.2) und JSR 338 (JPA 2.1) Gesch¨aftsf¨uhrer PMST GmbH . . . Bernd M¨uller, JAX 2014, 15.5.2014 4/61
  • 5. Arquillian Bernd M¨uller, JAX 2014, 15.5.2014 5/61
  • 6. Arquillian in der Selbstdarstellung Auszug aus http://www.arquillian.org/ So you can rule your code. Not the bugs. No more mocks. No more container lifecycle and deployment hassles. Just real tests! Bernd M¨uller, JAX 2014, 15.5.2014 6/61
  • 7. Kurzbeschreibung Arquillian JBoss’ Test-Framework f¨ur Tests im Container Dazu JUnit oder TestNG als Test-Runner Und Test-Enricher, um Tests im Container laufen zu lassen Und ShrinkWrap als Werkzeug f¨urs Packaging/Deployment Prinzipieller Ablauf: Test wird auf Client gepackt Test und Laufzeiterweiterung wird im Container deployt Test wird ausgef¨uhrt Testergebnisse werden an Client zur¨uckgegeben Test wird undeployt Aktuell: Arquillian Core Version 1.1.4.Final, 31.3.2014 Bernd M¨uller, JAX 2014, 15.5.2014 7/61
  • 8. Kurzbeschreibung Arquillian JBoss’ Test-Framework f¨ur Tests im Container Dazu JUnit oder TestNG als Test-Runner Und Test-Enricher, um Tests im Container laufen zu lassen Und ShrinkWrap als Werkzeug f¨urs Packaging/Deployment Prinzipieller Ablauf: Test wird auf Client gepackt Test und Laufzeiterweiterung wird im Container deployt Test wird ausgef¨uhrt Testergebnisse werden an Client zur¨uckgegeben Test wird undeployt Aktuell: Arquillian Core Version 1.1.4.Final, 31.3.2014 Bernd M¨uller, JAX 2014, 15.5.2014 7/61
  • 9. Kurzbeschreibung Arquillian JBoss’ Test-Framework f¨ur Tests im Container Dazu JUnit oder TestNG als Test-Runner Und Test-Enricher, um Tests im Container laufen zu lassen Und ShrinkWrap als Werkzeug f¨urs Packaging/Deployment Prinzipieller Ablauf: Test wird auf Client gepackt Test und Laufzeiterweiterung wird im Container deployt Test wird ausgef¨uhrt Testergebnisse werden an Client zur¨uckgegeben Test wird undeployt Aktuell: Arquillian Core Version 1.1.4.Final, 31.3.2014 Bernd M¨uller, JAX 2014, 15.5.2014 7/61
  • 10. Container, Deployments, Protokolle, Adapter 3 Betriebsmodi Embedded Container Managed Container Remote Container Protokolle Local (embedded) Servlet 2.5 / 3.0 JMX (nur JBoss) Container-Adapter JBoss-AS 4,5,6,7,8 Tomcat, Jetty GlassFish WebLogic WebSphere Im Zweifel: googeln und ausprobieren Bernd M¨uller, JAX 2014, 15.5.2014 8/61
  • 11. Container, Deployments, Protokolle, Adapter 3 Betriebsmodi Embedded Container Managed Container Remote Container Protokolle Local (embedded) Servlet 2.5 / 3.0 JMX (nur JBoss) Container-Adapter JBoss-AS 4,5,6,7,8 Tomcat, Jetty GlassFish WebLogic WebSphere Im Zweifel: googeln und ausprobieren Bernd M¨uller, JAX 2014, 15.5.2014 8/61
  • 12. Container, Deployments, Protokolle, Adapter 3 Betriebsmodi Embedded Container Managed Container Remote Container Protokolle Local (embedded) Servlet 2.5 / 3.0 JMX (nur JBoss) Container-Adapter JBoss-AS 4,5,6,7,8 Tomcat, Jetty GlassFish WebLogic WebSphere Im Zweifel: googeln und ausprobieren Bernd M¨uller, JAX 2014, 15.5.2014 8/61
  • 13. Beispiel: Test-Runner und Deployment @RunWith(Arquillian.class) public class CustomerServiceTest { @Deployment public static Archive <?> createTestArchive () { return ShrinkWrap.create(WebArchive.class , "test.war") .addClasses(Customer.class , CustomerService .class) .addAsResource("META -INF/persistence.xml") . addAsWebInfResource ( new File("src/main/webapp/WEB -INF/beans.xml")); } ... Bernd M¨uller, JAX 2014, 15.5.2014 9/61
  • 14. Beispiel: Test-Runner und Deployment @RunWith(Arquillian.class) public class CustomerServiceTest { @Deployment public static Archive <?> createTestArchive () { return ShrinkWrap.create(WebArchive.class , "test.war") .addClasses(Customer.class , CustomerService .class) .addAsResource("META -INF/persistence.xml") . addAsWebInfResource ( new File("src/main/webapp/WEB -INF/beans.xml")); } ... Bernd M¨uller, JAX 2014, 15.5.2014 9/61
  • 15. ShrinkWrap Werkzeug zur Erstellung/Manipulation von Java-Archiven (JARs, WARs, EARs) Fr¨uher eigenst¨andiges JBoss-Projekt, jetzt Arquillian-Teilprojekt Fluent-API zum Erstellen eines Archives, f¨ur sogenannte Micro Deployment, im Beispiel zwei Klassen und Deployment-Descriptoren Bernd M¨uller, JAX 2014, 15.5.2014 10/61
  • 16. Verbesserungspotenzial @Deployment public static Archive <?> createTestArchive () { return ShrinkWrap.create(WebArchive.class , generatedName) .addPackage(true , Customer.class.getPackage ()) .addAsResource("META -INF/test -persistence.xml", "META -INF/persistence.xml") . addAsWebInfResource (EmptyAsset.INSTANCE , "beans.xml"); } Generierter Deployment-Name Ganzes Package, optional mit Sub-Packages Spezieller Deployment-Descriptor f¨ur Test (JPA, CDI, . . . ) Leerer Deployment-Descriptor, auch String-Asset Bernd M¨uller, JAX 2014, 15.5.2014 11/61
  • 17. Verbesserungspotenzial @Deployment public static Archive <?> createTestArchive () { return ShrinkWrap.create(WebArchive.class , generatedName) .addPackage(true , Customer.class.getPackage ()) .addAsResource("META -INF/test -persistence.xml", "META -INF/persistence.xml") . addAsWebInfResource (EmptyAsset.INSTANCE , "beans.xml"); } Generierter Deployment-Name Ganzes Package, optional mit Sub-Packages Spezieller Deployment-Descriptor f¨ur Test (JPA, CDI, . . . ) Leerer Deployment-Descriptor, auch String-Asset Bernd M¨uller, JAX 2014, 15.5.2014 11/61
  • 18. Verbesserungspotenzial @Deployment public static Archive <?> createTestArchive () { return ShrinkWrap.create(WebArchive.class , generatedName) .addPackage(true , Customer.class.getPackage ()) .addAsResource("META -INF/test -persistence.xml", "META -INF/persistence.xml") . addAsWebInfResource (EmptyAsset.INSTANCE , "beans.xml"); } Generierter Deployment-Name Ganzes Package, optional mit Sub-Packages Spezieller Deployment-Descriptor f¨ur Test (JPA, CDI, . . . ) Leerer Deployment-Descriptor, auch String-Asset Bernd M¨uller, JAX 2014, 15.5.2014 11/61
  • 19. Verbesserungspotenzial @Deployment public static Archive <?> createTestArchive () { return ShrinkWrap.create(WebArchive.class , generatedName) .addPackage(true , Customer.class.getPackage ()) .addAsResource("META -INF/test -persistence.xml", "META -INF/persistence.xml") . addAsWebInfResource (EmptyAsset.INSTANCE , "beans.xml"); } Generierter Deployment-Name Ganzes Package, optional mit Sub-Packages Spezieller Deployment-Descriptor f¨ur Test (JPA, CDI, . . . ) Leerer Deployment-Descriptor, auch String-Asset Bernd M¨uller, JAX 2014, 15.5.2014 11/61
  • 20. Verbesserungspotenzial @Deployment public static Archive <?> createTestArchive () { return ShrinkWrap.create(WebArchive.class , generatedName) .addPackage(true , Customer.class.getPackage ()) .addAsResource("META -INF/test -persistence.xml", "META -INF/persistence.xml") . addAsWebInfResource (EmptyAsset.INSTANCE , "beans.xml"); } Generierter Deployment-Name Ganzes Package, optional mit Sub-Packages Spezieller Deployment-Descriptor f¨ur Test (JPA, CDI, . . . ) Leerer Deployment-Descriptor, auch String-Asset Bernd M¨uller, JAX 2014, 15.5.2014 11/61
  • 21. Beispiel: Zu testende EJB @Stateless public class CustomerService { @PersistenceContext EntityManager em; public void persist(Customer customer) { em.persist(customer ); } public long getNumberOfCustomers () { return em. createNamedQuery ( "Customer. getNumberOfCustomers ", Long.class ). getSingleResult (); } } Bernd M¨uller, JAX 2014, 15.5.2014 12/61
  • 22. Beispiel: Der Test @RunWith(Arquillian.class) public class CustomerServiceTest { @Deployment public static Archive <?> createTestArchive () { ...} @Inject CustomerService customerService ; @Test public void testPersist () { Customer customer = new Customer("Firstname", "Lastname" assertNull(customer.getId ()); // ueberfluessig customerService .persist(customer ); assertNotNull(customer.getId ()); } Bernd M¨uller, JAX 2014, 15.5.2014 13/61
  • 23. Beispiel: Alternativer Test @Test public void testPersist2 () { Customer customer = new Customer("Firstname", "Lastname" Long before = customerService . getNumberOfCustomers (); customerService .persist(customer ); Long after= customerService . getNumberOfCustomers (); assertTrue("Muss ein Customer mehr sein", before + 1 == after ); } Bernd M¨uller, JAX 2014, 15.5.2014 14/61
  • 24. Beispiel: 3. Alternative mit Persistenzkontext @RunWith(Arquillian.class) public class CustomerServiceTest { @PersistenceContext EntityManager em; @Test public void testPersist3 () { Customer customer = new Customer("Firstname", "Lastname" Long before = em. createNamedQuery ( "Customer. getNumberOfCustomers ", Long.class) . getSingleResult (); customerService .persist(customer ); Long after= em. createNamedQuery ( "Customer. getNumberOfCustomers ", Long.class) . getSingleResult (); assertTrue("Muss ein Customer mehr sein", before + 1 == after ); }
  • 25. Beispiel: 3. Alternative mit Persistenzkontext @RunWith(Arquillian.class) public class CustomerServiceTest { @PersistenceContext EntityManager em; @Test public void testPersist3 () { Customer customer = new Customer("Firstname", "Lastname" Long before = em. createNamedQuery ( "Customer. getNumberOfCustomers ", Long.class) . getSingleResult (); customerService .persist(customer ); Long after= em. createNamedQuery ( "Customer. getNumberOfCustomers ", Long.class) . getSingleResult (); assertTrue("Muss ein Customer mehr sein", before + 1 == after ); } Existiert, da Test in Container
  • 26. ” Richtige Anwendungen“: Multiple Deployments (Doku) @Deployment(name = "dep1", order = 1) public static WebArchive createDep1 () { ... } @Deployment(name = "dep2", order = 2) public static WebArchive createDep2 () { ... } @Test @OperateOnDeployment ("dep1") public void testRunningInDep1 () { ... } @Test @OperateOnDeployment ("dep2") public void testRunningInDep2 () { ... } Bernd M¨uller, JAX 2014, 15.5.2014 16/61
  • 27. Erweiterbarkeit Wie alle modernen Systeme/Frameworks besitzt Arquillian ein Service Provider Interface Aktuelle Erweiterungen: Drone (Web-UI) WARP (JSF) Persistence Performance Graphene (UI, AJAX) Seam 2 Bernd M¨uller, JAX 2014, 15.5.2014 17/61
  • 28. Arquillian Drone Bernd M¨uller, JAX 2014, 15.5.2014 18/61
  • 29. Arquillian Drone Arquillian-Erweiterung f¨ur funktionale Tests Basiert auf Selenium Selenium-Slogan: Selenium automates browsers WebDriver: M¨oglichkeit zur Browser-Steuerung, u.a. mit Java API WebDriver API das einzig neu zu lernende ¨Anderung des prinzipiellen Ablaufs: Tests auf Client Kombination Client und Server m¨oglich Version aktuell: 1.3.0.Final Version 2.0.0.Alpha1 mit ¨uberarbeitetem/entschlacktem API in Entwicklung (von uns nicht verwendet) Bernd M¨uller, JAX 2014, 15.5.2014 19/61
  • 30. Die n¨otigen Erweiterungen/¨Anderungen @RunWith(Arquillian.class) public class DroneUsedTest { @ArquillianResource URL deploymentURL; @Drone WebDriver driver; @Deployment(testable = false) public static Archive <?> createTestArchive () { ...} @ArquillianResource: das URL des Deployments @Drone: das WebDriver oder DefaultSelenium API Keine Tests im Server Bernd M¨uller, JAX 2014, 15.5.2014 20/61
  • 31. Die n¨otigen Erweiterungen/¨Anderungen @RunWith(Arquillian.class) public class DroneUsedTest { @ArquillianResource URL deploymentURL; @Drone WebDriver driver; @Deployment(testable = false) public static Archive <?> createTestArchive () { ...} @ArquillianResource: das URL des Deployments @Drone: das WebDriver oder DefaultSelenium API Keine Tests im Server Bernd M¨uller, JAX 2014, 15.5.2014 20/61
  • 32. Die n¨otigen Erweiterungen/¨Anderungen @RunWith(Arquillian.class) public class DroneUsedTest { @ArquillianResource URL deploymentURL; @Drone WebDriver driver; @Deployment(testable = false) public static Archive <?> createTestArchive () { ...} @ArquillianResource: das URL des Deployments @Drone: das WebDriver oder DefaultSelenium API Keine Tests im Server Bernd M¨uller, JAX 2014, 15.5.2014 20/61
  • 33. Die n¨otigen Erweiterungen/¨Anderungen @RunWith(Arquillian.class) public class DroneUsedTest { @ArquillianResource URL deploymentURL; @Drone WebDriver driver; @Deployment(testable = false) public static Archive <?> createTestArchive () { ...} @ArquillianResource: das URL des Deployments @Drone: das WebDriver oder DefaultSelenium API Keine Tests im Server Bernd M¨uller, JAX 2014, 15.5.2014 20/61
  • 34. Falls nicht nur Client-Tests @RunWith(Arquillian.class) public class DroneUsedTest { @Drone WebDriver driver; @Deployment public static Archive <?> createTestArchive () { ... } @Test @RunAsClient @InSequence (1) public void createCustomer( @ArquillianResource URL url) { @Test // im Server @InSequence (2) public void countCustomers () { ... } Auch Tests im Server m¨oglich, daher Unterscheidung Reihenfolge der Tests (Widerspruch zur reinen Lehre?)
  • 35. Falls nicht nur Client-Tests @RunWith(Arquillian.class) public class DroneUsedTest { @Drone WebDriver driver; @Deployment public static Archive <?> createTestArchive () { ... } @Test @RunAsClient @InSequence (1) public void createCustomer( @ArquillianResource URL url) { @Test // im Server @InSequence (2) public void countCustomers () { ... } Auch Tests im Server m¨oglich, daher Unterscheidung Reihenfolge der Tests (Widerspruch zur reinen Lehre?)
  • 36. Falls nicht nur Client-Tests @RunWith(Arquillian.class) public class DroneUsedTest { @Drone WebDriver driver; @Deployment public static Archive <?> createTestArchive () { ... } @Test @RunAsClient @InSequence (1) public void createCustomer( @ArquillianResource URL url) { @Test // im Server @InSequence (2) public void countCustomers () { ... } Auch Tests im Server m¨oglich, daher Unterscheidung Reihenfolge der Tests (Widerspruch zur reinen Lehre?)
  • 37. Versteht Arquillian Maven’s POM ? Nein, aber ShrinkWrap Es gibt einen ShrinkWrap-Resolver, der Maven und Gradle unterst¨utzt Jetzt Beispiel: JSF-Seite zur Kundenneuanlage Navigation zu Kundenanlage-Erfolgreich-Seite, falls kein Fehler Test, ob Navigation funktioniert Test, ob Daten im Server Bernd M¨uller, JAX 2014, 15.5.2014 22/61
  • 38. Versteht Arquillian Maven’s POM ? Nein, aber ShrinkWrap Es gibt einen ShrinkWrap-Resolver, der Maven und Gradle unterst¨utzt Jetzt Beispiel: JSF-Seite zur Kundenneuanlage Navigation zu Kundenanlage-Erfolgreich-Seite, falls kein Fehler Test, ob Navigation funktioniert Test, ob Daten im Server Bernd M¨uller, JAX 2014, 15.5.2014 22/61
  • 39. Das (fast) komplette Beispiel (Teil 1) @RunWith(Arquillian.class) public class CreateCustomerTest { private static final String WEBAPP_SRC = "src/main/webapp"; @Drone WebDriver driver; @Inject CustomerRepository customerRepository ; Bernd M¨uller, JAX 2014, 15.5.2014 23/61
  • 40. Das (fast) komplette Beispiel (Teil 2) @Deployment public static Archive <?> createTestArchive () { MavenDependencyResolver resolver = DependencyResolvers .use( MavenDependencyResolver .class) . loadMetadataFromPom ("pom.xml"); return ShrinkWrap.create(WebArchive.class , "test.war") .addPackages (...). addClasses (...) .addAsResource("META -INF/test -persistence.xml", "META -INF/persistence.xml") . addAsWebInfResource ("test -ds.xml") . addAsWebResource (new File(WEBAPP_SRC , "create.xhtml")) . addAsWebResource (new File(WEBAPP_SRC , "customer -created.xhtml")) . addAsWebInfResource (EmptyAsset.INSTANCE , "beans.xml") . addAsWebInfResource ( new StringAsset("<faces -config version ="2.0"/ >"), "faces -config.xml") .addAsLibraries ( resolver.artifact("org.seleniumhq.selenium:selenium -ja . resolveAsFiles ()); }
  • 41. Das (fast) komplette Beispiel (Teil 3) @Test @RunAsClient @InSequence (1) public void createCustomer( @ArquillianResource URL url) { driver.get(url + "create.jsf"); driver.findElement(By.id("create:firstname")) .sendKeys("firstname"); driver.findElement(By.id("create:lastname")) .sendKeys("lastname"); driver.findElement(By.id("create:dob")) .sendKeys("1.1.2000"); driver.findElement(By.id("create:email")) .sendKeys("email"); driver.findElement(By.id("create:password")) .sendKeys("password"); driver.findElement(By.id("create:create")). click (); assertTrue(driver.findElement( By.xpath("// body[contains(text(), ’Kunde angelegt ’)]")) .isDisplayed ()); }
  • 42. Das (fast) komplette Beispiel (Teil 4) @Test // im Server @InSequence (2) public void countCustomers () { assertEquals (1, customerRepository .getCustomers (). size ()); } Bernd M¨uller, JAX 2014, 15.5.2014 26/61
  • 43. @Drone im Detail Injection in Klasse Class-Based Life-Cycle Analog zu @BeforeClass / @AfterClass Injection in Methode Method-based Life-Cycle Analog zu @Before / @After Mehrere Injektionen ¨uber Qualifier m¨oglich Verschiedene Driver: WebDriver, FirefoxDriver, ChromeDriver, InternetExplorerDriver, SafariDriver Durch Selenium Unterst¨utzung von XPath-Ausdr¨ucken in Test-Asserts Bernd M¨uller, JAX 2014, 15.5.2014 27/61
  • 44. @Drone im Detail Injection in Klasse Class-Based Life-Cycle Analog zu @BeforeClass / @AfterClass Injection in Methode Method-based Life-Cycle Analog zu @Before / @After Mehrere Injektionen ¨uber Qualifier m¨oglich Verschiedene Driver: WebDriver, FirefoxDriver, ChromeDriver, InternetExplorerDriver, SafariDriver Durch Selenium Unterst¨utzung von XPath-Ausdr¨ucken in Test-Asserts Bernd M¨uller, JAX 2014, 15.5.2014 27/61
  • 45. @Drone im Detail Injection in Klasse Class-Based Life-Cycle Analog zu @BeforeClass / @AfterClass Injection in Methode Method-based Life-Cycle Analog zu @Before / @After Mehrere Injektionen ¨uber Qualifier m¨oglich Verschiedene Driver: WebDriver, FirefoxDriver, ChromeDriver, InternetExplorerDriver, SafariDriver Durch Selenium Unterst¨utzung von XPath-Ausdr¨ucken in Test-Asserts Bernd M¨uller, JAX 2014, 15.5.2014 27/61
  • 46. @Drone im Detail Injection in Klasse Class-Based Life-Cycle Analog zu @BeforeClass / @AfterClass Injection in Methode Method-based Life-Cycle Analog zu @Before / @After Mehrere Injektionen ¨uber Qualifier m¨oglich Verschiedene Driver: WebDriver, FirefoxDriver, ChromeDriver, InternetExplorerDriver, SafariDriver Durch Selenium Unterst¨utzung von XPath-Ausdr¨ucken in Test-Asserts Bernd M¨uller, JAX 2014, 15.5.2014 27/61
  • 47. @Drone im Detail Injection in Klasse Class-Based Life-Cycle Analog zu @BeforeClass / @AfterClass Injection in Methode Method-based Life-Cycle Analog zu @Before / @After Mehrere Injektionen ¨uber Qualifier m¨oglich Verschiedene Driver: WebDriver, FirefoxDriver, ChromeDriver, InternetExplorerDriver, SafariDriver Durch Selenium Unterst¨utzung von XPath-Ausdr¨ucken in Test-Asserts Bernd M¨uller, JAX 2014, 15.5.2014 27/61
  • 48. Arquillian WARP Bernd M¨uller, JAX 2014, 15.5.2014 28/61
  • 49. Arquillian Warp Client-seitige Tests mit Zusicherungen/Pr¨ufung von Server-seitiger Logik und Zustand Keine weiteren Bibliotheken, wie etwa Selenium, ben¨otigt Kein UI ben¨otigt (Headless) Speziell f¨ur Servlets und Servlet-basierte Systeme gemacht Im Augenblick nur Servlets direkt und JSF 2 unterst¨utzt Arquillian Spring Framework Extension enth¨alt Warp Spring MVC Extension (nicht betrachtet) Offizieller Nachfolger von JSFUnit Aktuell: Version 1.0.0.Alpha7, 11.3.2014 Bernd M¨uller, JAX 2014, 15.5.2014 29/61
  • 50. Die prinzipielle Idee hinter WARP Initiierung eines HTTP-Requests auf Client-Seite z.B. mit WebDriver Im selben Request-Zyklus Ausf¨uhren von Server-seitigen Tests im Container Dazu: Initiieren des Request ¨uber Interface Activity Inspizieren des Server-Zustands ¨uber Klasse Inspection Aktivity mit perform()-Methode Inspection mit JUnit/TestNG-Tests zum ” richtigen“ Zeitpunkt optional: Gruppieren und Observieren von Requests Bernd M¨uller, JAX 2014, 15.5.2014 30/61
  • 51. Die n¨otigen Erweiterungen/¨Anderungen @WarpTest f¨ur Test-Klasse @RunAsClient f¨ur Test-Klasse @BeforeServlet, @AfterServlet f¨ur Servlet-Tests @BeforePhase, @AfterPhase (6 Phasen) f¨ur JSF-Tests Im Folgenden 3 Beispiele Existieren die richtigen Beans? Validierung Navigation Bernd M¨uller, JAX 2014, 15.5.2014 31/61
  • 52. Die n¨otigen Erweiterungen/¨Anderungen @WarpTest f¨ur Test-Klasse @RunAsClient f¨ur Test-Klasse @BeforeServlet, @AfterServlet f¨ur Servlet-Tests @BeforePhase, @AfterPhase (6 Phasen) f¨ur JSF-Tests Im Folgenden 3 Beispiele Existieren die richtigen Beans? Validierung Navigation Bernd M¨uller, JAX 2014, 15.5.2014 31/61
  • 53. Die n¨otigen Erweiterungen/¨Anderungen @WarpTest f¨ur Test-Klasse @RunAsClient f¨ur Test-Klasse @BeforeServlet, @AfterServlet f¨ur Servlet-Tests @BeforePhase, @AfterPhase (6 Phasen) f¨ur JSF-Tests Im Folgenden 3 Beispiele Existieren die richtigen Beans? Validierung Navigation Bernd M¨uller, JAX 2014, 15.5.2014 31/61
  • 54. Die n¨otigen Erweiterungen/¨Anderungen @WarpTest f¨ur Test-Klasse @RunAsClient f¨ur Test-Klasse @BeforeServlet, @AfterServlet f¨ur Servlet-Tests @BeforePhase, @AfterPhase (6 Phasen) f¨ur JSF-Tests Im Folgenden 3 Beispiele Existieren die richtigen Beans? Validierung Navigation Bernd M¨uller, JAX 2014, 15.5.2014 31/61
  • 55. 1. Beispiel: Existieren die richtigen Beans? Weld-Manual: Einloggen ¨uber JSF-View-Bean Pr¨ufen auf Benutzername/Passwort ¨uber EJB CDI-produzierte Customer-Instanz im Session-Scope Die Existenz dieser Instanz soll ¨uberpr¨uft werden Bernd M¨uller, JAX 2014, 15.5.2014 32/61
  • 56. JSF Login-Bean @Named @SessionScoped public class Login implements Serializable { @Inject Credentials credentials; @Inject CustomerService customerService ; private Customer loggedInCustomer ; ... Bernd M¨uller, JAX 2014, 15.5.2014 33/61
  • 57. JSF Login-Bean (cont’d) public void login () { loggedInCustomer = customerService .getCustomer (... if ( loggedInCustomer == null) { FacesMessage message = new FacesMessage("Falsche ..."); FacesContext. getCurrentInstance (). addMessage (...); } } @Produces @LoggedIn Customer getloggedInCustomer () { return loggedInCustomer ; } public void logout () { loggedInCustomer = null; } Bernd M¨uller, JAX 2014, 15.5.2014 34/61
  • 58. Logged-In-Test @RunWith(Arquillian.class) @WarpTest @RunAsClient public class LoggedInTest { @Deployment public static Archive <?> createTestArchive () { // nichts besonderes } @ArquillianResource URL contextPath; @Drone WebDriver browser; Bernd M¨uller, JAX 2014, 15.5.2014 35/61
  • 59. Logged-In-Test (cont’d) @Test public void testLoggedIn () { browser.navigate ().to(contextPath + "login.jsf"); browser.findElement(By.id("form:email")). sendKeys(EMAIL ); browser.findElement(By.id("form:password")). sendKeys(PASSW Warp .initiate(new Activity () { public void perform () { browser.findElement(By.id("form:login")). click (); }}) .inspect(new Inspection () { private static final long serialVersionUID = 1L; @Inject @LoggedIn Customer customer; Bernd M¨uller, JAX 2014, 15.5.2014 36/61
  • 60. Struktur zur Verdeutlichung Warp .initiate(new Activity () { ... }) .inspect(new Inspection () { ... }) Aktivit¨at auf dem Client initiieren Inspektion auf dem Server ausf¨uhren Bernd M¨uller, JAX 2014, 15.5.2014 37/61
  • 61. Logged-In-Test (cont’d) Warp .initiate(new Activity () {...} ) .inspect(new Inspection () { private static final long serialVersionUID = 1L; @Inject @LoggedIn Customer customer; @BeforePhase(Phase. INVOKE_APPLICATION ) public void noCustomerExists () { Assert.assertNull( "LoggedIn Customer darf nicht existieren", customer ); } ... Bernd M¨uller, JAX 2014, 15.5.2014 38/61
  • 62. Logged-In-Test (cont’d) @BeforePhase(Phase. INVOKE_APPLICATION ) public void noCustomerExists () { Assert.assertNull( "LoggedIn Customer darf nicht existieren", customer ); } @AfterPhase(Phase. INVOKE_APPLICATION ) public void loggedInCustomerExists () { Assert.assertNotNull( "LoggedIn Customer muss existieren", customer ); Assert.assertEquals("Falsche E-Mail", EMAIL , customer.getEmail ()); Assert.assertEquals("Falsches Passwort", PASSWORD , customer.getPassword ()); } Bernd M¨uller, JAX 2014, 15.5.2014 39/61
  • 63. Logged-In-Test (cont’d) @BeforePhase(Phase. INVOKE_APPLICATION ) public void noCustomerExists () { Assert.assertNull( "LoggedIn Customer darf nicht existieren", customer ); } @AfterPhase(Phase. INVOKE_APPLICATION ) public void loggedInCustomerExists () { Assert.assertNotNull( "LoggedIn Customer muss existieren", customer ); Assert.assertEquals("Falsche E-Mail", EMAIL , customer.getEmail ()); Assert.assertEquals("Falsches Passwort", PASSWORD , customer.getPassword ()); } Bernd M¨uller, JAX 2014, 15.5.2014 39/61
  • 64. Logged-In-Test (cont’d) @BeforePhase(Phase. INVOKE_APPLICATION ) public void noCustomerExists () { Assert.assertNull( "LoggedIn Customer darf nicht existieren", customer ); } @AfterPhase(Phase. INVOKE_APPLICATION ) public void loggedInCustomerExists () { Assert.assertNotNull( "LoggedIn Customer muss existieren", customer ); Assert.assertEquals("Falsche E-Mail", EMAIL , customer.getEmail ()); Assert.assertEquals("Falsches Passwort", PASSWORD , customer.getPassword ()); } Bernd M¨uller, JAX 2014, 15.5.2014 39/61
  • 65. 2. Beispiel: Validierung Credentials werden falsch eingegeben (zu kurz) JSF erzeugt in Phase 3 FacesMessage-Instanzen Pr¨ufen vor und nach Phase 3, ob Messages existieren oder nicht Bernd M¨uller, JAX 2014, 15.5.2014 40/61
  • 66. Klasse Credentials @Named @RequestScoped public class Credentials { @NotNull @Size(min = 6, max = 30) private String email; @NotNull @Size(min = 6, max = 20) private String password; ... Deutsche Fehlermeldung f¨ur @Size: ”muss zwischen 6 ... Bernd M¨uller, JAX 2014, 15.5.2014 41/61
  • 67. Validierungstest @RunWith(Arquillian.class) @WarpTest @RunAsClient public class LoggedInValidationFailedTest { // nichts besonderes im Deployment @ArquillianResource URL contextPath; @Drone WebDriver browser; ... Bernd M¨uller, JAX 2014, 15.5.2014 42/61
  • 68. Validierungstest (cont’d) @Test public void testValidation () { browser.navigate ().to(contextPath + "login.jsf"); browser.findElement(By.id("form:email")). sendKeys("short") browser.findElement(By.id("form:password")). sendKeys("shor Warp .initiate(new Activity () { public void perform () { browser.findElement(By.id("form:login")). click (); }}) .inspect(new Inspection () { private static final long serialVersionUID = 1L; ... Bernd M¨uller, JAX 2014, 15.5.2014 43/61
  • 69. Validierungstest (cont’d) Warp .initiate(new Activity () {...} ) .inspect(new Inspection () { private static final long serialVersionUID = 1L; @ArquillianResource FacesContext facesContext; @BeforePhase(Phase. PROCESS_VALIDATIONS ) public void noFacesMessage () { Assert.assertEquals("Anzahl Fehler muss 0 sein", 0, facesContext.getMessageList (). size ()); } ... Bernd M¨uller, JAX 2014, 15.5.2014 44/61
  • 70. Validierungstest (cont’d) Warp .initiate(new Activity () {...} ) .inspect(new Inspection () { private static final long serialVersionUID = 1L; @ArquillianResource FacesContext facesContext; @BeforePhase(Phase. PROCESS_VALIDATIONS ) public void noFacesMessage () { Assert.assertEquals("Anzahl Fehler muss 0 sein", 0, facesContext.getMessageList (). size ()); } ... FacesContext injizierbar! Bernd M¨uller, JAX 2014, 15.5.2014 44/61
  • 71. Validierungstest (cont’d) .inspect(new Inspection () { ... @ArquillianResource FacesContext facesContext; @AfterPhase(Phase. PROCESS_VALIDATIONS ) public void facesMessagesExist () { List <FacesMessage > messages = facesContext.getMessageList (); Assert.assertTrue( facesContext.getMessageList (). size () != 0); for (FacesMessage facesMessage : messages) { Assert.assertTrue("Falsche Fehlermeldung", facesMessage.getSummary () .startsWith("muss zwischen 6")); } } Bernd M¨uller, JAX 2014, 15.5.2014 45/61
  • 72. 3. Beispiel: Navigation mit Redirect Einfache JSF-Seiten mit Navigation und Redirect Noch nicht erw¨ahntes WARP-Feature: Gruppieren von Inspektionen auf Server basierend auf Request-Folge Pr¨ufen der View-Id nach Restore-View-Phase Bernd M¨uller, JAX 2014, 15.5.2014 46/61
  • 73. JSF-Seiten mit Navigation redirect-source.xhtml <h:form id="form"> Seite verwendet #{ redirectSourceBean .name} <br /> <h:commandButton id="redirect" action=" redirect-target ? faces-redirect=true" value="Redirect to ’redirect-target .jsf ’" /> </h:form > redirect-target.xhtml <h:form id="form"> Seite verwendet #{ redirectTargetBean .name} /> </h:form > Bernd M¨uller, JAX 2014, 15.5.2014 47/61
  • 74. @RunWith(Arquillian.class) @WarpTest @RunAsClient public class RedirectTest { @Deployment public static Archive <?> createTestArchive () { return ShrinkWrap.create(WebArchive.class , "redirect -test.war") ... . addAsWebResource (new File(WEBAPP_SRC , "redirect -source.xhtml")) . addAsWebResource (new File(WEBAPP_SRC , "redirect -target.xhtml")) ... } @ArquillianResource URL contextPath; @Drone WebDriver browser; ... Bernd M¨uller, JAX 2014, 15.5.2014 48/61
  • 75. Navigationstest (cont’d) @Test public void testRedirect () { browser.navigate ().to(contextPath + "redirect -source.jsf") Warp .initiate(new Activity () { public void perform () { browser.findElement(By.id("form:redirect")). click (); }}) .group("redirect -source.jsf") .observe(HttpFilters.request (). index (1)) .inspect(new Inspection () { private static final long serialVersionUID = 1L; @AfterPhase(Phase.RESTORE_VIEW) ... Bernd M¨uller, JAX 2014, 15.5.2014 49/61
  • 76. Struktur zur Verdeutlichung Warp .initiate(new Activity () { ... }}) .group("redirect -source.jsf") // nur Doku .observe(HttpFilters.request (). index (1)) .inspect(new Inspection () { ... }) .group("redirect -target.jsf") // nur Doku .observe(HttpFilters.request (). index (2)) .inspect(new Inspection () { ... }) .execute (); Assert.assertTrue(browser.getCurrentUrl () .contains("redirect -target.jsf")); Bernd M¨uller, JAX 2014, 15.5.2014 50/61
  • 77. Navigationstest (cont’d) .group("redirect -source.jsf") .observe(HttpFilters.request (). index (1)) .inspect(new Inspection () { private static final long serialVersionUID = 1L; @AfterPhase(Phase.RESTORE_VIEW) public void verifyPage( @ArquillianResource FacesContext facesContext) { Assert.assertEquals("/redirect -source.xhtml", facesContext.getViewRoot (). getViewId ()); } }) Bernd M¨uller, JAX 2014, 15.5.2014 51/61
  • 78. Navigationstest (cont’d) .group("redirect -target.jsf") .observe(HttpFilters.request (). index (2)) .inspect(new Inspection () { private static final long serialVersionUID = 1L; @AfterPhase(Phase.RESTORE_VIEW) public void verifyPage( @ArquillianResource FacesContext facesContext) { Assert.assertEquals("/redirect -target.xhtml", facesContext.getViewRoot (). getViewId ()); } }) .execute (); Assert.assertTrue(browser.getCurrentUrl () .contains("redirect -target.jsf")); Bernd M¨uller, JAX 2014, 15.5.2014 52/61
  • 79. Auswahl des richtigen Request Da mehrere Request getriggert werden k¨onnen, muss man den richtigen (den, den man observieren will) ausw¨ahlen Dazu das HttpRequestFilter-Interface Damit spezifiziert man den zu verwendenden HttpRequest der aktuellen Gruppe Bernd M¨uller, JAX 2014, 15.5.2014 53/61
  • 80. Aus ” Dokumentation“ import static org.jboss.arquillian.warp .client.filter.http.HttpFilters.request; // will accept only requests for HTML ... group () .observe(request (). uri (). contains(".html")) // will accept only REST requests for JSON ... group () .observe(request (). header () .containsValue("Accept", "application/json")) // will accept only POST requests ... group () .observe(request (). method (). equal(POST )) Bernd M¨uller, JAX 2014, 15.5.2014 54/61
  • 81. Was kann alles injiziert werden? Injizierbar ¨uber @ArquillianResource Servlet-Ressourcen ServletRequest or HttpServletRequest ServletResponse or HttpServletResponse Bernd M¨uller, JAX 2014, 15.5.2014 55/61
  • 82. Was kann alles injiziert werden? (cont’d) Injizierbar ¨uber @ArquillianResource JSF-Ressourcen FacesContext Application ELContext, ELResolver, ExpressionFactory ExceptionHandler Flash NavigationHandler PartialViewContext RenderKit ResourceHandler StateManager UIViewRoot ViewHandler Bernd M¨uller, JAX 2014, 15.5.2014 56/61
  • 83. Wo Licht ist, ist auch Schatten Sehr schlechte Doku Noch viele/schwere Fehler Scheinbar Ein-Mann-Projekt: Luk´aˇs Fryˇc (Project Lead) Bernd M¨uller, JAX 2014, 15.5.2014 57/61
  • 84. Dokumentation WARP Bernd M¨uller, JAX 2014, 15.5.2014 58/61
  • 85. Zusammenfassung und (pers¨onliches) Fazit Einerseits . . . EAP Dokumentation enth¨alt kein Kapitel zu Arquillian JBoss Dokumentation enh¨alt kein Kapitel zu WARP Andererseits . . . EAP Quickstarts enthalten Arquillian-Tests JB225 Schulung enth¨alt Arquillian- und Drone-Tests Arquillian und Erweiterungen sehr leistungsf¨ahig und interessant Mein Rat: fangen Sie an ! Bernd M¨uller, JAX 2014, 15.5.2014 59/61
  • 86. Zusammenfassung und (pers¨onliches) Fazit Einerseits . . . EAP Dokumentation enth¨alt kein Kapitel zu Arquillian JBoss Dokumentation enh¨alt kein Kapitel zu WARP Andererseits . . . EAP Quickstarts enthalten Arquillian-Tests JB225 Schulung enth¨alt Arquillian- und Drone-Tests Arquillian und Erweiterungen sehr leistungsf¨ahig und interessant Mein Rat: fangen Sie an ! Bernd M¨uller, JAX 2014, 15.5.2014 59/61
  • 87. Zusammenfassung und (pers¨onliches) Fazit Einerseits . . . EAP Dokumentation enth¨alt kein Kapitel zu Arquillian JBoss Dokumentation enh¨alt kein Kapitel zu WARP Andererseits . . . EAP Quickstarts enthalten Arquillian-Tests JB225 Schulung enth¨alt Arquillian- und Drone-Tests Arquillian und Erweiterungen sehr leistungsf¨ahig und interessant Mein Rat: fangen Sie an ! Bernd M¨uller, JAX 2014, 15.5.2014 59/61
  • 88. Zusammenfassung und (pers¨onliches) Fazit Einerseits . . . EAP Dokumentation enth¨alt kein Kapitel zu Arquillian JBoss Dokumentation enh¨alt kein Kapitel zu WARP Andererseits . . . EAP Quickstarts enthalten Arquillian-Tests JB225 Schulung enth¨alt Arquillian- und Drone-Tests Arquillian und Erweiterungen sehr leistungsf¨ahig und interessant Mein Rat: fangen Sie an ! Bernd M¨uller, JAX 2014, 15.5.2014 59/61
  • 89. Referenzen Arquillian Reference Guide JSF Testing John D. Ament. Arquillian Testing Guide. Packt Publishing, 2013. Bernd M¨uller, JAX 2014, 15.5.2014 60/61
  • 90. Fragen und Anmerkungen Bernd M¨uller, JAX 2014, 15.5.2014 61/61