Aliens and iPhones
Intro
For some, testing has become an important part of the development lifecycle. There are a bunch of popular testing frameworks out there for both client and server. JBoss is pushing Arquillian, which takes testing to the next level by allowing you to test in a container, thus effectively testing how your code would work on the server it will eventually run on. Lets call these tests integration tests.
Now, there are numerous articles on Arquillian.org that show how to get started and what the goals of the project are, so I won’t go into all that here. What i’m really interested in, is how the project relates to a mobile environment. That great that we can server-side code in our container, for instance JBoss AS 7, but what about client side?
Task
There are client libraries that do unit testing, such as qunit, but what about actual integration tests where we can control the browser. Some people use Selenium, which has a suite of different products to help control the browser. There seems to be a lot of setup. I just want to integrate this into the tests i already have in my maven build. How?
You may remember that i mentioned Arquillian, you should it was 1 paragraph ago. Well, Arquillain has a project called Drone, that basically wraps all the selenium stuff up and is managed by the Arquillian framework. This should allow me to run these new client integration tests along side my server-side tests.
Setup
I’ll be assuming that this pre reqs have already been met:
java sdk 6.0+
maven 3.0+
IDE of choice, I use IntelliJ
Git
JBoss AS 7.
Firefox //for this part atleast
Time
Note: Some of this stuff we are going to be trying is in Alpha, so expect it to change. Also there seems to be a decent amount of setup, maven stuff, for Arquillian, so just be patient
The project that we will be modifying will be the HTML5 Kitchensink example from AeroGear found here . Also, I must give credit to Karel Piwko for his awesome presentation at JavaOne. I’ll be borrowing some code from him. Check out his repo here
First things first, Lets create a new branch, called drone, to work with so we don’t pollute the master branch:
$ git checkout -b drone
Since this is a maven project, we can easily import this into my IDE.
Just to make sure everything runs ok in the IDE, lets run the provided test with the arq-jbossas-remote maven profile. Make sure you have AS 7 running before running it
It should pass since we haven’t modified anything yet.
This would be a good spot to stop and get something to drink, eat, go to the bathroom or whatever. The next steps could take a while. I can wait…………..
Ok….Now it’s time to dive in.
Start
First thing is to create a new test class. All i did was copy the current test MemberRegistrationTest.java and named the copy MemberRegistrationClientTest.java
Then I removed everything except for the @Deployment stuff and add a little something.:
@RunWith(Arquillian.class)
public class MemberRegistrationClientTest {
@Deployment(testable = false) //This is to tell Arquillian we want Client Mode
public static Archive<?> createTestArchive() {
return ShrinkWrap.create(WebArchive.class, "test.war")
.addClasses(Member.class, MemberService.class, MemberRepository.class,
MemberRegistration.class, Resources.class)
.addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml")
.addAsWebInfResource("arquillian-ds.xml")
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
}
}
Ok, quick sin/cos ( high five to anyone who understands this ). I really like sublime text, especially the multi row select. Ok, back to the show.
Next, we need to package our application, including all the web resources, for deployment and testing in the container. I changed the file a little bit, since packaging all the “web” stuff takes a little bit of effort. I add a helper method to create my deployments:
public static WebArchive createDeployment() {
return createTestDeployment();
}
public static WebArchive createTestDeployment() {
WebArchive war = ShrinkWrap.create(WebArchive.class)
.addClasses(Member.class, MemberService.class, MemberRepository.class,
MemberRegistration.class, Resources.class, JaxRsActivator.class)
.merge(
ShrinkWrap.create(GenericArchive.class)
.as(ExplodedImporter.class)
.importDirectory("src/main/webapp")
.as(GenericArchive.class),"/")
.addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml")
.addAsWebInfResource("arquillian-ds.xml")
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
System.out.println(war.toString(true)); // this will show you what is packaged
return war;
}
OK, time to add some dependencies to our pom.xml. We are going to be using the Drone extensions from Arquillian so we need to add those.
First, make sure in the dependecyManangment section we have this as our first dependency:
<dependency>
<groupId>org.jboss.bom</groupId>
<artifactId>jboss-javaee-6.0-with-tools</artifactId>
<version>${jboss.bom.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Note: the version should be 1.0.2.Final and it should be specified in the properties
Now, there should be some Arquillian dependencies already in this file, find them and put this under them:
<dependency>
<groupId>org.jboss.arquillian.extension</groupId>
<artifactId>arquillian-drone-webdriver-depchain</artifactId>
<type>pom</type>
<scope>test</scope>
</dependency>
Ok, now we can get back to code. In our test lets add a resource to get us the URL context.
@ArquillianResource
URL contextUrl;
And also create a test that will open FireFox and display the homepage of our app
@Test
public void openFireFoxHomePage(@Drone FirefoxDriver driver) {
driver.get(contextUrl.toString()); }
For those following along, our new test class should look something like this:
@RunWith(Arquillian.class)
public class MemberRegistrationClientTest {
@ArquillianResource
URL contextUrl;
@Deployment(testable = false)
public static WebArchive createDeployment() {
return createTestDeployment();
}
public static WebArchive createTestDeployment() {
WebArchive war = ShrinkWrap.create(WebArchive.class)
.addClasses(Member.class, MemberService.class, MemberRepository.class,
MemberRegistration.class, Resources.class, JaxRsActivator.class)
.merge(ShrinkWrap.create(GenericArchive.class).as(ExplodedImporter.class).importDirectory("src/main/webapp"). as(GenericArchive.class),"/")
.addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml")
.addAsWebInfResource("arquillian-ds.xml")
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
return war;
}
@Test
public void openFireFoxHomePage(@Drone FirefoxDriver driver) {
driver.get(contextUrl.toString());
}
}
You should now be able to debug this test in an IDE, set a breakpoint and see the browser come up.
Here is the code up to this point: Tag 0.0.1.drone
Here is my forked repo: Drone Branch
Next Up
Now that we have a working test on Firefox, lets try to automate it and submit something, then a Mobile Browser( since that was the point of this post).