Blog

Friday, 8 February 2013

Faster Arquillian and Graphene 2 test development

Tired of long turnaround when writing tests with Arquillian and Graphene 2?
Thanks to Pavol Pitonak we've learned how to speed test development up by order of magnitude.

Graphene 2 allows you to efficiently test user interfaces of web applications. You write the simple test code and run it in your IDE or with Maven and Graphen takes care of starting selenium server, lunching the web browser and do the clicking.

Sounds fantastic, but when you are developing the test the time between running the test, fixing it and running again is too long. It's pure waste.
It's because for each run the selenium-server needs to be started and a new session be created.
For deveopment purposes we can speed it up by starting selenium server ourselves in standalone mode and configuring Arquillian to reuse existing session.

Here are few simple steps to achieve that:

1. Download Selenium Server in standalone version from https://code.google.com/p/selenium/downloads/list. For example:
https://selenium.googlecode.com/files/selenium-server-standalone-2.29.0.jar

2. Run it with command:
java -jar selenium-server-standalone-2.29.0.jar

3. Create new Maven project. If you want to use Arquillian with Graphene 2 and WebDriver, you should add these dependencies to your pom.xml:

If you want to use JUnit in standalone mode:

<dependency>
   <groupId>org.jboss.arquillian.junit</groupId>
   <artifactId>arquillian-junit-standalone</artifactId>
   <version>1.0.3.Final</version>
   <scope>test</scope>
</dependency>
or in container mode:
<dependency>
   <groupId>org.jboss.arquillian.junit</groupId>
   <artifactId>arquillian-junit-container</artifactId>
   <version>1.0.3.Final</version>
   <scope>test</scope>
</dependency>
rest of dependencies:
<dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.8.2</version>
   <scope>test</scope>
</dependency>

<!-- Graphene dependency chain - imports all other dependencies required -->
<dependency>
   <groupId>org.jboss.arquillian.graphene</groupId>
   <artifactId>arquillian-graphene</artifactId>
   <version>2.0.0.Alpha2</version>
   <type>pom</type>
   <scope>test</scope>
</dependency>

<!-- Graphene WebDriver -->
<dependency>
   <groupId>org.jboss.arquillian.graphene</groupId>
   <artifactId>graphene-webdriver</artifactId>
   <version>2.0.0.Alpha3</version>
   <type>pom</type>
   <scope>test</scope>
</dependency>
For a few dependencies above, you should have added JBoss repository to Maven's settings.xml or alternatively add repository directly in project pom.xml file, like this:
<repository>
  <id>JBOSS_NEXUS</id>
  <url>http://repository.jboss.org/nexus/content/groups/public</url>
</repository>
4. Now, you should specify, which browser will be used to execute tests. I assume, you have Firefox in your computer. So, in next step you should add arquillian.xml to project in /src/test/resources directory. Example configuration, with Firefox as default browser for WebDriver:
<?xml version="1.0" encoding="UTF-8"?>
<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">

   <!-- configuration for graphene2 -->
   <extension qualifier="webdriver">
       <property name="browserCapabilities">firefox</property>
       <property name="remoteReusable">true</property>
   </extension>
</arquillian>
The essential property is "remoteReusable", which instructs graphene to reuse existing session, so that the browser is opened only once and reused for following test runs.

Other useful property would be "remoteAddress" in case your selenium server runs on different port or host.
<property name="remoteAddress">http://localhost:4444/wd/hub</property>
5. At the end, you can write new test. Simple empty test class should look like this:
@RunWith(Arquillian.class)
public class GrapheneTest {

    @Drone
    WebDriver driver;

    @Test
    public void testHappyPath(){
        driver.get("http://www.google.com");
        String pageTitle = driver.getTitle();
        Assert.assertEquals(pageTitle, "Google"); 
    }
}
Finally, you can run tests from your IDE or trough mvn test command.

Browser session is preserved across the tests, so if you need to reset browser cookies between tests, you can add this line whenever deleting cookies is needed.
driver.manage().deleteAllCookies();
To automate clearing cookies between tests, you should use @Before annotation:
@Before
private void beforeEachTest(){
 driver.manage().deleteAllCookies();
}
If JUnit is in standalone mode, you should be aware of this bug: ARQ-1070 , but versions from pom.xml included above seems not affected, @Before annotation works fine.

Useful links