A blog about my life, thoughts and work. This blog will consist of programming, philosophy, politics, poetry and anything else that I want to talk about.
March 09, 2012
Selenium, HtmlUnit, JavaScript and JQuery - Writing Performant Tests
I finally got time a couple of weeks ago to investigate the problem and because I tend to avoid JavaScript like the plague, it took me a little while to garner the necessary skills and utilities to diagnose the problems.
I thought I would share the lessons I learnt in case anyone else comes across similar problems.
The first thing I did was to upgrade all the libraries to their latest versions this often fixes performance bugs and can highlight problems with the code base. In my case it only garnered a minor speed up but highlighted the fact that the old version of Selenium we were using allowed interaction with hidden and disabled HTML elements and a number of our tests were badly written.
The second thing I discovered is that the Selenium / HtmlUnit event model means that SELECT element change events were only fired when focus changed to another element in the page.
Seeing no major speed increase I instead reverted to profiling the Java processes. We don't have access to a commercial profiler but a remarkable amount can be achieved using VisualVM which is included as part of the Sun JDK since about version 6.012.
The first thing you should always do when installing this utility is to increase the memory available using the VisualVM options file in the JDK configuration folders.
I was very careful to limit what I profiled to only a certain subset of the classes involved as even with the tweaked memory settings VisualVM is a little flaky when profiling large, long-running processes.
I used the CPU profiling capability and focused in on the projects test classes, the Selenium classes and the HtmlUnit classes.
After a certain amount of faffing around I discovered that a large amount of time was spent in the JavaScript and particularly around event bubbling and DOM change listening.
Unfortunately there is a certain level of indirection involved in the JavaScript implementation and could not discover precisely which JavaScript elements were involved even when using Java debugging.
I instead reverted to using FireBug and FireQuery to profile and navigate through the JavaScript within Firefox. I quickly discovered some obvious JavaScript performance problems and fixed them. Equally rapidly I discovered that the performance characteristics of the Firefox JavaScript engine is very different to those of the HtmlUnit JavaScript engine - Mozilla Rhino.
FireBug and FireQuery were excellent for helping me to understand what was executing and would be perfect for profiling browser performance issues, I would have to look elsewhere for the root cause of the HtmlUnit performance problems.
I resorted to old-school - comment stuff out until it broke or performed faster.
The problem was rapidly resolved to being the use of JQuery live() methods. They are designed to handle events highly dynamic DOMs by listening to events that have bubbled all the way up to the root and then matching the source of the event to a selector before calling the method intended to handle the event.
I replaced them with JQuery bind() and delegate() methods and saw a massive performance increase: A UI test suite that took 26 minutes to run completed in 10.
I learnt that highly dynamic JQuery based scripting could cause severe test performance problems and learnt a lot about how it worked. Longer term I'm going to move to statically bound JavaScript as much as possible particularly when I need to be able to test it.
A framework like JQuery is a little like an iceberg, it may look like you're barely using any JavaScript but under the surface...
- Posted using BlogPress from my iPad
September 08, 2011
On the Insanity of Expecting Nothing to Happen...
On my current project we're building an asynchronous message based system with various outputs, in particular a file for consumption by a mainframe.
On a number of occasions tests have been written that assert that something has not happened.
When you're testing synchronous processes this is a perfectly reasonable assertion to make, when the process returns all the work will be done.
For asynchronous processes?When the process returns then you have no direct way of knowing if it has completed.
For many people the most obvious way of checking that something has not happened in an asynchronous process is the counterpart for checking that something has happened asynchronously. You put in a timeout.
The problem with this is the likelihood of a given outcome. When expecting something to happen asynchronously you only have to wait until it has happened which means that you only ever wait until the timeout when something has gone wrong. When expecting something not to happen, you end up waiting for the time out most of the time. This means that for every assertion that nothing will happen you end up adding a fixed timeout that causes your test phase to increase in duration.
When you use a time out to wait for something not to happen, you risk setting the timeout too short and the test becoming invalid because the thing you asserted wouldn't happen occurs after the test completes. This can lead to further increases in the timeouts to ensure that the tests remain valid.
There is a related problem with testing asynchronous processes where the test only checks an intervening step in the process before moving on the next test. This leaves you open to side effects from the processes started by the preceding tests causing hard to diagnose problems with your later tests. This is particularly likely with tests that assert that something doesn't happen as they have a greater chance of leaving the test before the process under test has completed.
How do we avoid these problems and still be able to make assertions that something hasn't happened?
The 'Sentinel' pattern is a good place to start.
Send a second request after the first that will produce a result after the first has completed, in this way you can assert that if you only see the result of the second request then you can state that the first request hasn't produced anything. Maybe you can ask the asynchronous process to do two things in one request and can then assert that only the effects of the additional work are visible.
Alternatively you can look at other ways of knowing that the process under test has completed. Check the logging for a statement that is only produced when the process has completed or maybe introduce an event or message that is produced when the process completes regardless of whether the other output is produced.
It is always a bad idea to expect 'nothing' to happen asynchronously, always expect something.
April 04, 2011
Debugging Neo4J Spatial - Update 3 on Neo4J Spatial and British Isles OSM Data import.
March 31, 2011
Update 2 on Neo4J Spatial and British Isles OSM Data import.
March 24, 2011
Update 1 on Neo4J Spatial and British Isles OSM Data import.
package com.presynt.neo4j;
import static org.junit.Assert.*;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import org.geotools.referencing.CRS;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.neo4j.gis.spatial.Layer;
import org.neo4j.gis.spatial.SpatialDatabaseService;
import org.neo4j.gis.spatial.SpatialTopologyUtils;
import org.neo4j.gis.spatial.osm.OSMImporter;
import org.neo4j.gis.spatial.osm.OSMLayer;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.kernel.EmbeddedGraphDatabase;
import org.neo4j.kernel.impl.batchinsert.BatchInserterImpl;
import javax.xml.stream.XMLStreamException;
import java.io.IOException;
public class TestNeo4JSpatial {
private static GraphDatabaseService graphDB;
private static SpatialDatabaseService spatialDB;
@Test
@Ignore
public void createSpatialDB() throws XMLStreamException, IOException {
OSMImporter importer = new OSMImporter("OSM-BUCKS");
BatchInserterImpl inserter = new BatchInserterImpl("/testDB");
importer.importFile(inserter ,"/OSMData/buckinghamshire.osm");//"british_isles.osm"); // "C:\\british_isles.osm");
inserter.getGraphDbService().shutdown();
graphDB = new EmbeddedGraphDatabase("/testDB");
importer.reIndex(graphDB, 100000);
graphDB.shutdown();
}
@Test
public void retrieveLayer(){
final Layer layer =
spatialDB.getLayer("OSM-BUCKS");
assertNotNull(layer);
assertEquals(OSMLayer.class, layer.getClass());
}
@Test
public void useLayer() {
final OSMLayer osmLayer = (OSMLayer)spatialDB.getLayer("OSM-BUCKS");
final GeometryFactory factory = osmLayer.getGeometryFactory();
System.out.println("Unit of measure: " + CRS.getEllipsoid(osmLayer.getCoordinateReferenceSystem()).getAxisUnit().toString());
final Point point = factory.createPoint(new Coordinate(51.808721,-0.689735));
// final Layer boundaryLayer = osmLayer.addSimpleDynamicLayer("boundary", "administrative");
// SearchContain searchContain = new SearchContain(point);
// boundaryLayer.getIndex().executeSearch(searchContain);
// for(SpatialDatabaseRecord record: searchContain.getResults()){
// System.out.println("Container:" + record);
// }
final Layer highwayLayer = osmLayer.addSimpleDynamicLayer("highway", null);
long startTime = System.currentTimeMillis();
SpatialTopologyUtils.findClosestEdges(point, highwayLayer, 10.0);
System.out.println("10m took:" + ((System.currentTimeMillis() - startTime) / 1000d) +"s");
startTime = System.currentTimeMillis();
SpatialTopologyUtils.findClosestEdges(point, highwayLayer, 10.0);
System.out.println("10m took:" + ((System.currentTimeMillis() - startTime) / 1000d) +"s");
startTime = System.currentTimeMillis();
SpatialTopologyUtils.findClosestEdges(point, highwayLayer, 100.0);
System.out.println("100m took:" + ((System.currentTimeMillis() - startTime) / 1000d) +"s");
startTime = System.currentTimeMillis();
SpatialTopologyUtils.findClosestEdges(point, highwayLayer, 100.0);
System.out.println("100m took:" + ((System.currentTimeMillis() - startTime) / 1000d) +"s");
startTime = System.currentTimeMillis();
SpatialTopologyUtils.findClosestEdges(point, highwayLayer, 1000.0);
System.out.println("1000m took:" + ((System.currentTimeMillis() - startTime) / 1000d) +"s");
startTime = System.currentTimeMillis();
startTime = System.currentTimeMillis();
SpatialTopologyUtils.findClosestEdges(point, highwayLayer, 1000.0);
System.out.println("1000m took:" + ((System.currentTimeMillis() - startTime) / 1000d) +"s");
SpatialTopologyUtils.findClosestEdges(point, highwayLayer, 10000.0);
System.out.println("10000m took:" + ((System.currentTimeMillis() - startTime) / 1000d) +"s");
startTime = System.currentTimeMillis();
SpatialTopologyUtils.findClosestEdges(point, highwayLayer, 10000.0);
System.out.println("10000m took:" + ((System.currentTimeMillis() - startTime) / 1000d) +"s");
startTime = System.currentTimeMillis();
// for(SpatialTopologyUtils.PointResult result : SpatialTopologyUtils.findClosestEdges(point, highwayLayer, 10000.0)){
// System.out.println(result);
// }
}
@BeforeClass
public static void initialiseDatabase() {
graphDB = new EmbeddedGraphDatabase("target/test-classes/spatialTestDB");
spatialDB = new SpatialDatabaseService(graphDB);
}
@AfterClass
public static void shutdownDatabase() {
graphDB.shutdown();
spatialDB = null;
graphDB = null;
}
}
March 21, 2011
Neo4J Spatial and Importing the British Isles Open Street Map Data
- org.neo4j:neo4j:1.3.M04
- org.neo4j:neo4j-spatial:0.5-SNAPSHOT
- org.geotools:gt-referencing:2.6.5
- org.geotools:gt-main:2.6.5
- org.geotools:gt-cql:2.6.5
- org.geotools:gt-epsg-hsql:2.6.5
- com.vividsolutions:jts:1.11
October 12, 2010
My Web Comics...
- Butternutquash - Telling the tales of a group of friends that hang around a comic strip. It is far more cynical than you would expect but always funny. I love the Narcoleptic Dog.
- Ctrl+Alt+Del - A delightfully odd ball comic strip following the personal and imaginary life of a dedicated gamer.
- Diesel Sweeties - The life and loves of an assorted group of people, including a fading porn actress her sometime boyfriend - a robot, a chronic hipster, a Canadian, a very disturbing furry and the list goes on. This comic strip has resulted in some of my favourite T-Shirts.
- Girl Genius - A gloriously drawn story of an orphaned. young woman who discovers that she has inherited the 'Spark' from her parents; the ability to build amazing steam-punk devices. This is a complex and involving tale set in a richly realised world.
- Gunnerkrigg Court - I only discovered this recently - A comic that becomes more beautiful as the artist develops his skill. telling the story of a conflict between science and magic through the eyes of a young girl thrown into the middle.
- Kukuburi - By the artist of Butternutsquash. Again a fabulously beautiful comic strip set in a seemingly dream world. Now sadly on hiatus but well worth reading.
- Orneryboy - A richly humorous gothic story about a couple who live with Brian the Zombie and three cats, one of whom is a ghost.
- Penny Arcade - A pure geek gamers comic strip but highly entertaining if you get the jokes. I'm a particular fan of Catsby and Twisp who crop up from time to time.
- PvP - The Godfather of web comics. Many web cartoonists cite Scott Kurtz as their influence both artistically and professionally. He is credited with pioneering making web cartooning a viable career. The comic itself follows the adventures of a bunch of journalists working at a games magazine.
- Scary-Go-Round - A very British comic strip and all the better for it. Over the years it has mutated but always centres around ordinary people living very un-ordinary lives.
- Sluggy Freelance - For a comic strip that started as a little story about a group of house mates this has developed into one of the richest and most perpetually rewarding comic strips that I read. Dimension hopping, big guns and humour make this a firm favourite. One character in particular should always be mentioned: Bun-Bun a psychotic dwarf lop rabbit with a flick-knife.
- The Abominable Charles Christopher - Tough to describe as it follows the perambulations of a perpetually innocent hairy beast that is largely man-shaped. He says nothing but still converses freely with the animals of the forest. Just before the summer break he has found himself face to face with a human town. I love it for the art and the crazy animal characters.
- User Friendly - One of the oldest web comics. I was introduced to this many years ago by my friend Neil. Gloriously anarchic tales told of an Internet Service Provider's support team with occasional visits by characters of the Cthulhu pantheon.
September 28, 2010
Further Forays Into the HTML5 Stack - Animation
September 20, 2010
Forays into the HTML5 stack.
- It is significantly more mature as a specification than the HTML 5 Canvas element.
- The HTML 5 canvas element is procedural in its rendering so with a command it renders pixels directly to screen and so does not have a screen graph; the SVG xml elements are the scene graph and are embedded directly in the DOM and so are manipulable using all the tricks that we are familiar with. This also means that a lot of the heavy lifting for re-drawing is done for us.
- Text is more of a first class citizen in SVG and so is easier to make available to Accessible browsers.
- SVG graphics elements are style-able using CSS.
- HTML can also be embedded back into SVG (and manipulated via the DOM) using the foreignObject element
- The default SVG animation framework is built around the SMIL standard which is pretty low level and is not always the easiest to work with though it is very powerful. I'm intending to see how well SVG interacts with the CSS3 animation effects which are much nicer to work with.
- SVG support is present in the latest iteration of all the browsers but is patchy to say the least. The best of the moment is the WebKit family, Firefox is the next best though it has big issues with the text rendering. IE9 claims to be a huge step forwards over IE8 but I have yet to try out the beta and there are question marks over how well it will support SVG animation.
- While its text support is good there is one glaring omission - word wrap. The neatest work-around is to embed an appropriate HTML element in the SVG using foreignObject.
September 15, 2010
My life with BDD...
- Given: The remainder of the sentence defines pre-conditions for the next steps of the scenario.
- When: Defines activity that the system under test is carrying out as part of the test.
- Then: The assertions that the test should be checking.
September 12, 2010
Some New Social Networking Infrastructure
August 29, 2010
Lyrical Ambiguity in the Kinks' Lola
One thing that always makes me stop and wonder is how many people believe firmly that they know the gender of Lola.
To me it seems that they have missed the brilliance of the lyrical ambiguity. The lines that really seem to be misunderstood are: "But I know what I am and I'm glad I'm a man and so is Lola.". Most people I talk to who have yet to get it believe firmly that the lines indicate that Lola is a man.
This interpretation arises from the belief that "so is Lola" refers to the fragment "I'm a man". This is a perfectly valid interpretation of the lyric but ignores another equally valid interpretation.
There is another fragment that could be referred to by "so is Lola"; "I'm glad I'm a man". If this is the reference then the interpretation would be that Lola is also glad that the protagonist is a man thus leaving Lola's gender entirely unstated.
In many ways this is the aural equivalent of the face/vase illusion where you can see either the faces or the vase but not both.
Whatever else it is, it is a brilliant song with brilliant lyrics.
- Posted using BlogPress from my iPad
July 05, 2010
iPhone 4 has arrived...
Faced a rather unique problem... I got two iPhones in my package rather than the one I expected. The nice young customer service rep nearly fell off her seat when I called and told her about it. The first time they had heard of that happening.
I think that I slightly restored her faith in humanity as she thought that no one would have called up and would have just stayed quiet about it. She asked me to drop off the extra to a store and gave me a nice in-store credit.
I'm now on my way to London waiting for the new SIM to activate and just using the iPhone as an iPod. I'm hoping that the rest of the experience is as painless as the iPad was.
- Posted using BlogPress from my iPad
June 30, 2010
My First Track day...

On Monday I took my life into my hands and went on a track day at Bedford Autodrome with EasyTrack.co.uk.
I had a blast! The track was ideal for a novice and my car (an Audi TT RS) proved more than capable. I had asked for a session with an instructor and I got a great guy named Steve. In the end I took a second session in the afternoon. As a result I went from being slowest on the track to not being the slowest by a decent margin. There were some fabulous drivers on the track that day, the two sticking in my mind included one in a GT3 RS and an utter genius in a bog standard MX5.
I've included a photo that was taken by TrackPhoto.co.uk.
- Posted using BlogPress from my iPadJune 27, 2010
The Height of Geekery
Well, here I am at my favourite cafe for breakfast with my iPad. I'm trying the whole blogging from my iPad thing with an app called BlogPress.
It's really interesting to see how modern integrated technology is making it feasible to do things that would have been awkward if not impossible a few years ago. The opportunities in this space are endless.
The excitement about the potential for location based services is well known. Unfortunately the excitement can obscure the real win. Location-less Services. The fact that I can start doing this kind of thing truly independently of my location is what's exciting. There have been some early mis-fires with the excitement of being able to take a laptop with you on holiday. Lugging a laptop though is really pretty hard work. We're on the cusp of being able to access and interact with the "datasphere" anywhere in the world.
This is where reading science fiction is a great advantage. Writers have been exploring how to use this for years. I feel that I am ready to make use of this and build on their thinking to go places that people who have not been reading will never think of.
How about you?
- Posted using BlogPress from my iPad
Location:Cliffe High St,Lewes,United Kingdom
June 17, 2010
Constructor Versus Setter Based Dependency Injection
There seems to be two extreme camps here and no middle ground.
I, as usual, agree with neither extreme.
The simple fact is that my preferred approach is to design classes that meet the original intent of object orientation. That the class is fully usable after construction.
That is not to say that I believe that Constructor injection is the one, true way. Rather, I believe that all mandatory dependencies should be configured in the constructor and optional ones should be satisfied by setter methods. This makes the class much easier to understand. It also means that the constructor does not end up completely overloaded with parameters but neither are you left looking at a a sea of setter methods wondering which ones have to be used.
By using this convention the code becomes more self-documenting.
March 19, 2010
The problem with modern 3D films
February 10, 2010
What do I think about Business Analysis?
- Working with the business to understand the business domain.
- Capturing and documenting business requirements.
- Analyse the business domain to highlight areas of inconsistency and identify areas of uncertainty.
- Distill and communicate the business requirements to the implementation team.
November 03, 2009
A First Attempt at Haiku
October 26, 2009
Octopussies...

Nope - I'm not referring to multiples of a James Bond Film - I'm referring instead to a family tradition.
My mother has for as long as I can remember given an 'Octopussy' to the young children of family and friends. An Octopussy is a friendly octopus crocheted out of wool:
To start the body:
- Make a chain of 6 or 7 stitches and then form a circle using whatever colour wool you have to hand..
- Using double crochet make a flat circle about 2 or 3 inches in diameter.
- Continue adding rows to the circle without increasing the number of stitches and this will form a cup shape.
- Change to white to continue in order to make a space for the eyes to be embroidered.
- Continue until you have a nice wide band for the eyes.
- Start trimming the edge with double crochet in a contrasting colour going through the middle of the chain.
- Continue down to one end and crochet in the long strands.
- Turn and do a second row of double crochet and turn again to give a 3 row 'foot'.
- Continue until you reach the end that you started with.
- Using the loose strands from each of the feet pull them through the flat circle at the base of the body and tie them off to attach the legs.
- Embroider the eyes.
- Change colour from the white to whatever colour you like.
- Continue with crochet decreasing with each row.
- When you are close to the end stuff the body with a non-toxic filling (my mother uses a form of foam chips).
- finish the top of the body and pull final thread through to lose it in the body.
- Make a long chain with two or three strands of wool.
- Pull the chain halfway through the top of the Octopussy placing a knot so that it cannot be shifted.
- The chain can then be tied onto a convenient point so that the Octopussy cannot be thrown out of a pram or cot.
It also has the advantage of leaving the child with a friendly view of Octopi!