In this article we will walk through the HTMLUnit library to learn how to test Web applications. You can combine HTMLUnit with Arquillian to test Jakarta Faces applications with ease.
What is HTML Unit?
HTMLUnit is a Java-based testing tool that allows developers to automate testing of web applications. It simulates a web browser, allowing users to test the functionality and behavior of a web application as if it were being accessed through a web browser.
One of the main benefits of using HTMLUnit is that it is lightweight and easy to use. It requires no installation and you can run it from the command line or integrated into a build tool such as Maven or Gradle. You can also use HTMLUnit in conjunction with other testing frameworks. For example with JUnit and Arquillian, to create more comprehensive test suites.
To use HTMLUnit for testing a web application, the developer first needs to create a Java project and add HTMLUnit as a dependency. Once the project is set up, the developer can use the HTMLUnit API to navigate to a web page, fill out forms, and interact with elements on the page. For example, the following code navigates to the Google homepage and searches for the term “HTMLUnit”:
WebClient webClient = new WebClient(); HtmlPage page = webClient.getPage("http://www.google.com"); HtmlForm form = page.getFormByName("f"); HtmlTextInput textField = form.getInputByName("q"); textField.setValueAttribute("HTMLUnit"); HtmlButton button = form.getButtonByName("btnK"); page = button.click();
HTMLUnit also allows developers to test the rendering and layout of web pages by providing a DOM (Document Object Model) representation of the page. This allows developers to verify that the page is rendered correctly and that elements are positioned as expected.
One of the limitations of HTMLUnit is that it does not support JavaScript, which can be a problem for web applications that rely heavily on JavaScript for their functionality. However, HTMLUnit does provide a way to enable JavaScript support by using the Rhino engine, which is a JavaScript implementation written in Java.
Besides, if you are developing server-based applications using Jakarta Server Faces you won’t need to mess up with Javascript code. As proof of concept, in the next section we will show how to test an application using Jakarta Server Faces using HTMLUnit and Arquillian.
Tesing a JSF Application
To test HTMLUnit we will reuse a simple Jakarta Faces application from one of our tutorials. This application csontains a Form with input text fields. By submitting the Form, the CDI Beans will add a row to a DataTable element that is in the same page.
For the sake of simplicity, we will show here just the index.xhtml page. The full source code is available at the end of this article.
Here is the index.xhtml page:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="jakarta.faces.core" xmlns:ui="jakarta.faces.facelets" xmlns:h="jakarta.faces.html" > <h:head> <h:outputStylesheet name="style.css" /> </h:head> <h:body> <h2>JSF Basic demo</h2> <h:form id="formpanel"> <h:panelGrid columns="2" styleClass="default"> <h:outputLabel for="name" value="Name: " /> <h:inputText id="name" value="#{user.name}" /> <h:outputLabel for="name" value="Surname: " /> <h:inputText id="surname" value="#{user.surname}" /> <h:outputLabel for="name" value="Email: " /> <h:inputText id="email" value="#{user.email}" /> <h:commandButton id="submit" actionListener="#{manager.save}" styleClass="buttons" value="Save" /> <h:messages errorStyle="color: red" infoStyle="color: green" /> <br/> <ui:debug/> </h:panelGrid> </h:form> <br/> <h:form id="datatableform" > <h:dataTable id="mytable" name="mytable" value="#{userList}" var="item" styleClass="table" headerClass="table-header" rowClasses="table-odd-row,table-even-row"> <h:column> <f:facet name="header">Name</f:facet> <h:outputText value="#{item.name}" /> </h:column> <h:column> <f:facet name="header">Surname</f:facet> <h:outputText value="#{item.surname}" /> </h:column> <h:column> <f:facet name="header">Email</f:facet> <h:outputText value="#{item.email}" /> </h:column> <h:column> <f:facet name="header">Delete</f:facet> <h:commandButton actionListener="#{manager.delete(item)}" styleClass="buttons" value="Delete" /> </h:column> </h:dataTable> </h:form> </h:body> </html>
The index.xhtml view should look like that when you deploy it on WildFly and add an entry:
Next, we will build a simple test with HTMLUnit and Arquillian to do exactly the same thing.
Coding our Arquillian Test with HTMLUnit
- Firstly, we need to define our test as ArquillianTest.
- Then, we will add a @Deployment method which creates a WebArchive by importing it from the target folder of the Maven application
- Finally, we will add @Before and @After methods to bootstrap and stop the WebClient interface, which is represent the browser when you work with HtmlUnit:
@RunWith(Arquillian.class) public class CustomerIT { @ArquillianResource private URL webUrl; private WebClient webClient; @Deployment(testable = false) public static WebArchive createDeployment() { return create(ZipImporter.class, "jsf-demo.war") .importFrom(new File("target/jsf-demo.war")) .as(WebArchive.class); } @Before public void setUp() { webClient = new WebClient(); } @After public void tearDown() { webClient.close(); } // test here }
Next, let’s add a Test method in our Class:
@Test public void test() { try { // Navigate to the Home page HtmlPage page = webClient.getPage(webUrl + "index.xhtml"); // Get input text 'name' and set a value HtmlInput name = (HtmlInput) page.getElementById("formpanel:name"); name.setValueAttribute("john"); // Get input text 'surname' and set a value HtmlInput surname = (HtmlInput) page.getElementById("formpanel:surname"); surname.setValueAttribute("smith"); // Get input text 'email' and set a value HtmlInput email = (HtmlInput) page.getElementById("formpanel:email"); email.setValueAttribute("[email protected]"); HtmlSubmitInput submit = (HtmlSubmitInput) page.getElementById("formpanel:submit"); // Get a new HtmlPage after submitting HtmlPage page2 = submit.click(); // Iterate on the Table final HtmlTable table = page2.getHtmlElementById("datatableform:mytable"); for (final HtmlTableRow row : table.getRows()) { System.out.println("Found row"); for (final HtmlTableCell cell : row.getCells()) { System.out.println(" Found cell: " + cell.asNormalizedText()); } } } catch (Exception e) { System.out.println(e.getClass()); e.getMessage(); } }
In order to interact with our Web page, we can use the HTML Components which are available under the package com.gargoylesoftware.htmlunit.html. For example, the HtmlInput component represents an Input Text.
In the first part of our Test, we are setting some values in the Text fields.
Next, we are clicking the Submit button to send the data to the Server-Side CDI Beans. Please notice that the click() method returns a new HtmlPage with the updated DOM.
Finally, we are iterating over the DataTable JSF Component. Behind the hoods, the DataTable is an HTML Table. Therefore, we can use the HtmlTable Class to fetch the content of it.
The example includes two Arquillian Profiles to test our application. Make sure you have configured your JBOSS_HOME in the src/test/resources/arquillian.xml file:
<arquillian xmlns="http://jboss.org/schema/arquillian" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd"> <!-- Example configuration for a managed WildFly instance --> <container qualifier="jboss" default="true"> <configuration> <property name="jbossHome">/home/francesco/jboss/wildfly-27.0.0.Final</property> <property name="managementPort">9990</property> <property name="managementAddress">localhost</property> </configuration> </container> </arquillian>
Finally, test the application. To run a remote Test:
mvn clean package verify -Parq-wildfly-remote
You should see the Datatable output from the Arquillian Test:
Found cell: Name Found cell: Surname Found cell: Email Found cell: Delete Found row Found cell: john Found cell: smith Found cell: [email protected] Found cell: Delete
Conclusion
This article was a quickstart to learn how to use HTMLUnit as testing framework for Web application. HTMLUnit provides a simple way to test server-side application such as Jakarta Faces.
Source code: https://github.com/fmarchioni/mastertheboss/tree/master/web/test-jsf