Testing Ajax with Arquillian

With ever growing demands on a rich and highly interactive user interface across a wide range of devices, automated testing becomes a crucial part of development routine. To my experience, it is often arguable whether the effort spent on writing tests really pays off. Arquillian is a tool I value for its ease of use and overall effectiveness. Today, I would like to share an example of how Arquillian can be used to test an Ajax-driven web application.


To keep the demo easy to follow the application is limited to choosing a preferred color. This idea is not mine. After some googling around I got inspired by an example at Rob's.




The screenshot above shows a home page of a user called demo. Now, the challenge is to ensure the application interacts as expected. As you can see there is a bunch of items on the page we could use in our tests. First of all, the successful login is confirmed by a welcome message. Secondly, the username is displayed in a designated box. Next, notice that a default color is grey. Finally, we keep track of the time the page was last loaded. Since this is supposed to be Ajax, we want the page be fully loaded once and once only.

That calls for a handful of Selenium / Sahi scripts. Well, first things first. Has this actually been deployed yet? With Arquillian, you take control of this initial step in an amazingly elegant manner:
@RunWith(Arquillian.class)
public class SimpleWebTest {
  ..
  import org.jboss.arquillian.junit.Arquillian;
  import org.jboss.arquillian.container.test.api.Deployment;
  import org.jboss.shrinkwrap.api.spec.WebArchive;
  import org.jboss.shrinkwrap.api.ShrinkWrap;
  import org.jboss.shrinkwrap.api.asset.EmptyAsset;
  ..
  @Deployment(testable=false)
  public static WebArchive createDeployment() {
    return ShrinkWrap.create(WebArchive.class, "login.war")
           .addClasses(Credentials.class, User.class, Login.class)
           .addAsWebResource(getFile("login.xhtml"))
           .addAsWebResource(getFile("home.xhtml"))                
           .addAsWebInfResource(getFile("faces-config.xml"))
           .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
  }
  ..
}
Think an enhanced JUnit. Arquillian integrates a number of technologies, each of which is designed for a specific task. ShrinkWrap provides a straightforward and powerful API for assembling Java applications. By using the @Deployment annotation, Arquillian guarantees the application gets deployed before any test is run. What I like in particular is that once the last test is over the deployment is automatically disposed of. All the hassle with the initial setup and the subsequent tear-down boils down to a single annotation. 
To make this happen we have to tell Arquillian where to find the application server. In the arquillian.xml:
<container qualifier="jboss7" default="true">
    <configuration>
      <property name="jbossHome">
         /Users/tom/apps/jboss-as-7.1.1.Final
      </property>
    </configuration>
  </container>
Let's move on the actual testing. The application is powered by JSF 2.0 and all server calls are asynchronous to cater for partial page updates. Testing Ajax could be cumbersome. Fortunately, Arquillian provides an enhanced Selenium extension called Graphene which makes this task really simple:
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.ajocado.framework.GrapheneSelenium;
import static org.jboss.arquillian.ajocado.Graphene.waitForXhr;
import static org.jboss.arquillian.ajocado.Graphene.id;
..
public static final IdLocator CHANGE_COLOR_BUTTON 
                          = id("menu:changeColor");
..
@Drone
private GrapheneSelenium browser;
..
// The button click triggers an Ajax request.
waitForXhr(browser).click(CHANGE_COLOR_BUTTON);
// The change is done. Let's test the results
..
Another feature I find extremely useful is the ability to capture screenshots during the test execution. To me, the ability to visually retrospect substantial UI changes increases credibility of the automated testing and adds to overall confidence in the development team. Capturing a screen boils down to a single call:
browser.captureScreenshot();
In fact, it is way too simple. I would expect I could pass a file name as argument. Nevertheless, I was able to work around this limitation by using the ImageIO library:
import javax.imageio.ImageIO;
..
ImageIO.write(browser.captureScreenshot(), "png", 
   new File("screenshots/" + filename + ".png"));
..
Here is an example of what to expect. Notice the highlighted radios:



All in all, I enjoyed using Arquillian and see a great potential in it. The only drawback is a lengthy list of maven dependencies. I won't bore you with further details, all you need is to read the docs, first two guides will do.

That's all I wanted to say today. As usual, the source code is attached at the end of the post. Next time, I will look into Arquillian on a mobile platform.


Download Source Code or Explore It