Beispiel: Unit-Test der Webschicht mit Maven und Arquillian Drone


Inhalt:

Arquillian Drone
Änderungen am Servlet
Code des Tests
Ausführen des Tests
Typ des verwendeten Browsers


Für WildFly 35 und JakartaEE10: : hier wird ein Unit-Test für ein EAR-Projekt, bestehend aus EJB-Projekt und Web-Projekt, unter Verwendung des Arquillian-Framework, mittels Maven erstellt und deployed.

Dieses Beispiel basiert komplett auf dem Beispiel Unit-Test mit Maven und Arquillian und erweitert es nur um einen Unit-Test der Webschicht.

Hier gibt es das gepackte Eclipse-Projekt zum Download: StatelessMaven.zip. Die Importanleitung findet man im Stateless Session Bean und Maven-Beispiel.


Arquillian Drone

Arquillian Drone (https://github.com/arquillian/arquillian-extension-drone/) ist eine Arquillian-Komponente, die für den Test von Webanwendungen genutzt werden kann: sie erlaubt es, innerhalb des Tests Webseiten aufzurufen, Formulare auszufüllen und abzusenden und HTML-Rückgaben des Servers auszuwerten und zu prüfen.
Arquillian Drone bildet eine Kapsel um den Selenium WebDriver (https://www.seleniumhq.org/). Dieser bildet eine API, um diverse Browser zu steuern, indem Aufrufe über die Automationsschnittstelle des jeweiligen Browsers geleitet werden.
Doku von Arquillian Drone: https://arquillian.org/arquillian-extension-drone/
Doku des Selenium WebDriver: https://www.selenium.dev/documentation/

Änderungen am Servlet

Damit die vom GeometricModelServlet berechneten Werte ausgewertet werden können, werden die beiden Ergebnisse "Oberfläche" und "Volumen" in span-Tags geklammert und diesen wird ein Name (oder alternativ eine ID) gegeben:
 
        printWriter.write("Volume = <span name=\"volume\">" + dblVolume + "</span>, Surface = <span name=\"surface\">" + dblSurface + "</span>\r\n" + "<br><br><br>\r\n");

Code des Tests

Vorbereitung: Fürs Compilieren des Code müssen zwei Änderungen durchgeführt werden:
Im "pom.xml" des Root-Projekts wird im Element "dependencyManagement" die "Bill of Materials" von Drone zugefügt, hier in der Version "3.0.0-alpha.8":
	<dependencyManagement>
		<dependencies>
			...
			
			<dependency>
				<groupId>org.jboss.arquillian.extension</groupId>
				<artifactId>arquillian-drone-bom</artifactId>
				<version>3.0.0-alpha.8</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
        
		</dependencies>
	</dependencyManagement>


In "pom.xml" von "StatelessMaven-web" wird im Element "dependencies" die "arquillian-drone-webdriver-depchain" zugefügt:

	<dependencies>
		...
		<dependency>
			<groupId>org.jboss.arquillian.extension</groupId>
			<artifactId>arquillian-drone-webdriver-depchain</artifactId>
			<type>pom</type>
			<scope>test</scope>
		</dependency>
	</dependencies>
Wir müssen eine Versionsnummer angeben, da sie nicht implizit mitgeliefert wird. Wir verwenden die Version "3.0.0-alpha.8", da wir im letzten Kapitel auch die Verwendung von Firefox als Browser zeigen wollen und die stable Releases 2.5.x mit aktuellen Browser-Versionen eventuell nicht mehr funktionieren (z.B. mit Google Chrome).


Der Wert "test" des Elements "scope" bedeutet, dass diese Abhängigkeit nur zur Compilierung und Ausführung von Testklassen zur Verfügung steht, aber nicht im regulären Code der Anwendung.

Wichtig: danach im Contextmenü "Maven" => "Update Project" aufrufen!


Analog zum Beispiel "Unit-Test mit Maven und Arquillian" wird hier ein Integrationstest verwendet. D.h. im Webprojekt wird im Unterverzeichnis "src\test" die Klasse de.hsrm.jakartaee.knauf.statelessmaven.web.test.ServletIT (der Zusatz "IT" markiert sie als Integrationstest) zugefügt:
Testklasse

Sie hat diesen Code:
package de.hsrm.jakartaee.knauf.statelessmaven.web.test;

import java.net.URL;

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.junit5.ArquillianExtension;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

@ExtendWith(ArquillianExtension.class)
@RunAsClient
public class ServletIT
{
    @Deployment
    public static Archive<?> getEarArchive()
    {
       ...
    }

    @Drone
    private WebDriver browser;
    
    @ArquillianResource()
    private URL deploymentUrl;

    @Test
    public final void browserTest() throws Exception
    {
        System.out.println("Testing client website ... " + deploymentUrl);
        
        //Zur Startseite navigieren:
        browser.get(deploymentUrl.toString() + "servlet/GeometricModelServlet");
        
        //Formular ausfüllen:
        browser.findElement(By.name("a")).sendKeys("7");
        browser.findElement(By.name("b")).sendKeys("8");
        browser.findElement(By.name("c")).sendKeys("9");
        //Formular abschicken:
        browser.findElement(By.name("submit")).click();

        //Ergebnisse auswerten:
        String volume = browser.findElement(By.name("volume")).getText();
        Assert.assertEquals("504.0", volume);
        
        String surface = browser.findElement(By.name("surface")).getText();
        Assert.assertEquals("382.0", surface);
    }
}

Im Detail:


Ausführen des Tests

Siehe Beispiel Unit-Test mit Maven und Arquillian.
Da ich hier zwei Integrationstests habe, wird die EAR-Datei zweimal auf den WildFly-Server deployed und wieder entfernt.


Typ des verwendeten Browsers

Der Selenium WebDriver verwendet in der Defaulteinstellung HtmlUnit (http://htmlunit.sourceforge.net/ und https://github.com/HtmlUnit/htmlunit) - ein "Browser" ohne GUI, wie man an der Logausgabe bei der Testausführung sieht:
Jan. 16, 2022 12:23:49 NACHM. org.jboss.arquillian.drone.webdriver.factory.AbstractWebDriverFactory createConfiguration
INFO: Property "browser" was not specified, using default value of htmlunit

In der Datei "arquillian.xml" kann man auf einen anderen Browser umschalten:

<arquillian ...>
	<extension qualifier="webdriver">
		<property name="browser">firefox</property>
	</extension>
</arquillian ...>
Im Beispiel wird Firefox verwendet. Dies erfordert natürlich einen installierten Firefox.
Bei Ausführung des Tests sieht man in der Konsole, dass ein Firefox-Prozess gestartet wird, und es öffnet sich auch kurz ein Firefox-Fenster mit der Webseite unserer Anwendung und schließt sich dann wieder:
1739702105529	geckodriver	INFO	Listening on 127.0.0.1:34634
1739702105638	mozrunner::runner	INFO	Running command: "C:\\Program Files\\Mozilla Firefox\\firefox.exe" "--marionette" "--remote-debugging-port" "12035" "--remote ... ocalhost:12035/,http://[::1]:12035/" "-no-remote" "-profile" "C:\\Users\\USERNAME\\AppData\\Local\\Temp\\rust_mozprofileSateDp"

Stand 16.02.2025
Historie:
16.02.2025: erstellt aus JavaEE8-Beispiel, WildFly 35