Thursday, April 9, 2009

Playing with Hudson for running UI tests

I have a whole bunch of UI automation tests that for one reason of another I never gotten around to running them automatically. I had planned to include them in our short regression tests sequence; but they are just not stable enough at the moment. The problem with testing UI in a complicated environment such as JDeveloper as it only take a minor change by someone else to derail your tests. So I wanted an environment I could run them locally in.

I decided to use Hudson to drive the tests after being impressed by it at a presentation at JavaOne last year. I don't have to worry about building the product, only testing the results of the build system. It is very easy to set up, just download the war and either deploy it to a container or just run it from the command line and its starts its own server.

Now while Hudson has lots of nice support for various source control systems it of course doesn't support Oracle's in-house ADE source control system. Also I was kinda worried that since as control our build with make that it would be hard to integrate. I shouldn't have worried as Hudson has some really nice scripting support which makes integration to any SCM system really quite easy. Perhaps I will write a proper integration one day; but not really necessary for what I need to do day to day.

Anyhow a job can be made up of multiple steps, be they script, ant or maven. Here is a fragment of a job I set up to work out what the latest labels are of each of our current development branches. This might seem like an odd thing to do; but you can trigger hudson jobs off changes in a given URL if you install the right plugin - strangely there isn't one that will trigger of a script.

There are loads of plugins and they are easily installed using the hudson plugin manager ("/pluginManager"), just make sure that you pass in the proxy options at the command line if they are not set up in your environment so it can contact the home server. The Xvnc, Emma and URL Change Trigger plugins are the most important as far I am concerned.

Hudson can run multiple jobs concurrently; but for the purposes of running tests in JDeveloper I only want one running at a time as it means I can rely on default ports on all of my tests. So I reduced the number of executors to 1 on the configuration page ("/configure"). It did have to restart the server to get this to take effect though.

As mentioned before I am using the URL trigger to cause new jobs to run, you can configure this on your job configuration page ("/job/%job_name%/configure").

At the bottom of this page you can also configure how the results of the build steps are processed. In this case capturing junit and emma results. I also want to archive the results of the automation tests, we take a screen grab at the end of each test failure and capture a log of all http traffic. This all gets collected up for each test.

For each job you get a nice overview of test results and coverage, not particular proud of the test coverage values here but it is something I am working on...

Obviously with UI tests you need a display per test run, now with only run executor this isn't so much of a problem; but if you wanted to run multiple tests on the same machine then you should make use of the Xvnc plugin and turn it on for the relevant tests. This create a new vncserver for each job and configure the DISPLAY environment variable correctly. One important thing to consider is to make sure you are running the tests in the same environment as your users. VNC default to running tvm; but for a higher level test tool such as Abbot to work properly you need to run a proper window manager. So I edit my ~/.vnc/xstartup as follows to run gnome, note the "--sm-disable" mean you can run multiple instances concurrently:

#!/bin/sh
[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
vncconfig -iconic &

gnome-session --choose-session=VNC  --sm-disable &

The other thing to consider is that the default display dimensions for xvnc is too small to run big complex Swing application. You can control the command line options on the hudson top level configuration page. It would be nice to be able to configure this for each job.

I guess the reason why I like this system so much is that it was easy to set up and you got a lot for the time you have invested. This are load more features, particularly in the area of notification with everything from email to rss to teddy bear lamps. The ability of Hudson to bring a machine in to the build pool by just running a WebStart application is also intriguing and something I am going to look at as I pull a windows machine into the build pool when my desktop become avaliable.

Wednesday, April 8, 2009

Google AppEngine to support Java?

This is pretty cool, finding somewhere to host lightweight java applications can be a pain. I will be interesting to see if I can deploy to this directly from JDeveloper so signed up to see if I can get on the preview list. Looks like it will support Servlet so -WS and -RS services should work in theory.

Update: Google also have a Eclipse plugin out to make this all a bit easier.

Monday, April 6, 2009

Another way to write out an XML document in Java

This comes from the "you learn something everyday" department as I am currently reviewing a book on XML and JDeveloper. Now Java has some perfectly good APIs to load XML documents; but nothing standard to write them out again. Mostly you either end up casting to a particular implementation class or using the XLST with an identity transformer.

TransformerFactory tFactory =
    TransformerFactory.newInstance();
Transformer identityTransformer = tFactory.newTransformer();
identityTransformer.transform(
  new DOMSource(document),
  new StreamResult(...));

It turns out that in version 3.0 of DOM they added support for APIs to load and save XML documents. They do suffer from the non-Java weirdness of all the DOM apis; but you can use then to write out an XML document:


import java.io.FileWriter;

import java.io.IOException;

import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;


DOMImplementation impl = DOMImplementationRegistry.newInstance()
    .getDOMImplementation("Core 3.0");
DOMImplementationLS feature = (DOMImplementationLS)impl.getFeature("LS", "3.0");

Document doc = impl.createDocument("http://www.example.com", "fred", null);

LSOutput output = feature.createLSOutput();
output.setCharacterStream(
    new FileWriter("/tmp/output.xml"));
LSSerializer serializer = feature.createLSSerializer();
serializer.write(
    doc, output);

Unfortunately I still think that the XLST code is more compact. You might consider the DOM version if you want to be more obvious in your intent.

Thursday, March 26, 2009

Filtering RSS feeds in Thunderbird

Now most test automation systems will generate a RSS feed of some kind; this is all well and good; but it can be a pain to read if you component is just one of many.

I wanted a filtered version of the feed that would only show up if my component had caused a test failure. It turns out you can do this in Thunderbird, the internal nature of the website rules out Yahoo Tubes et al.... Select the feed you want to get a filtered version of and do New->Saved Search.... give the feed a name and pick where you want the search to turn up. I like importatnt stuff in my inbox so that is what I choose as the location:

You can then filter based on various terms. One problem is that you can only search in the content of the RSS feed not the web page you get directed to. A colleague of mine who maintains a goodly part of the test infrastructure made a quick change to include the broken components in the feed body (Thanks to Chris Lewis for being very patient with me on this). So in my case I can simple do:

Now because we are good developers at the moment I cannot show you a screen shot with a broken test. Nor can I show you a screen grab of an another teams failure as this would be strictly against the Oracle blogging policy. :-)

Wednesday, March 18, 2009

Super type tokens

Now I read quite a bit of Java code but I always make an effort to understand each bit of code that passes by my desk and I do still get some surprises. Whilst looking at some jersey client code I noticed the following line.

 public List<StatusBean> getFriendsTimelineJson() {
           return wr.path("statuses/friends_timeline.json")
                   .header(AUTHENTICATION_HEADER, authentication)
                   .accept(MediaType.APPLICATION_JSON_TYPE)
                   .get(new GenericType<List<StatusBean>>() {
           });
 }

Note the final parameter in the builder that take a instance of "GenericTypeList" which appears to be some kind of anonymous type. It turns out to be a clever workaround for generic type erasure.

Consider the following method:

public <T> T getFavorite(Class<T> klass) {
    return ...;
}

Type erasure means the following won't compile:

   List<String> list = thing.getFavourite(List<String>.class);

Using a "super type token" solve this problem as generic types are not erased from class definitions, so you can write:

   List<String> list = thing.getFavourite(
       new GenericType<List<String>>() {});

With the following implementation of the getFavourite method: (See GenericType.java)

public <T> T getFavorite(GenericType<T> klass) {
    return getFavourite(klass.getRawClass());
}

You can also see this used in fest-reflect API for the same reasons. (TypeRef in the FEST API example)

Providing SOAP / JSON / AMF / .NET / etc services from Java

There is an interesting project over at codehaus called enunciate. It is a maven task that can take a basic bean and publish in a variety of format including -WS SOAP, -RS REST and AMF along with type safe clients for many different platform. (I would strongly argue that the difference between REST-lite and REST would required a major architecture change not possible with this simple transform.)

The AMF version is particularly interesting as it would make providing services for Flash application more straightfoward. There is more on how it was put together with JAX-RS over on dzone.

Twiiter client in Jersery

Just a quick link to a example twitter client built with the Jersey client API. Note the lack of structure compared with say a JAX-WS client.