Thursday, March 09, 2006

Cruise Control and X10 devices - the fiddly bits

Cruise control integrates nicely with X10 - which is great if you want to light up a lavalamp (or a life sized dancing pirate) to indicate build results.

So, you'd probably want to add a line like this to your Cruise Control config file.



You'd want two for the red/green combination, passing onWhenBroken="false" to the green one and using a different device code.

The main thing to note is that the java comm library is braindead with regards to
finding the javax.comm.properties file. If you can, install Cruise Control to a
directory without any spaces. If not, follow below.

Installed Without Spaces (in windows):

The current (2.4.1) build of Cruise Control doesn't supply win32com.dll or the javax.comm.properties files, but does supply comm.jar and x10.jar. Get these from: here (Update: sun no longer distributes to windows version, GO SUN!) . Put javax.comm.properties and win32com.dll in the same directory as the comm.jar file.

Installed With Spaces
(in windows):

Follow the instructions above.

The comm jar does some lame classpath parsing to find the javax.comm.properties
file. This means that you must:

- Have the comm.jar outside of any implicitly defined library directory -
so you need to have it in the classpath somehow.

- The directory this file lives in must not have a space.

- The javax.comm.properties files must live in exactly the same place as the jar file.

So the easiest way is to:

make a c:\javacomm directory
put comm.jar and javax.comm.properties in c:\javacomm
add c:\javacomm\comm.jar to the start of the cruise control classpath

Why didn't they just do getResource("javax.comm.properties")?? I dunno.


Other notes:

- set the CCDIR environment variable to where you installed cruise control - but append \main underneath it.

so C:\Program Files\CruiseControl-x.y.x\main

Also see the note on http://cruisecontrol.sourceforge.net/main/configxml.html about copying
win32com.dll if you need to.

Hopefully that will fill in the missing bits that I've not seen anyone mention before.

Wednesday, March 01, 2006

Unit Testing JavaScript from within Java

(Reposted for the benefit of the Agile Planetters)

So you're developing a web app. You're probably using Java. You might even be using some of that super cool AJAX. But with all that logic on the client side, you better be sure you're testing it.

You could use JsUnit - that's an excellent solution, as it can be run from multiple real browsers ensuring the code works the way it should with that particular javascript implementation. Unfortunately, we don't want to have to do separate tests - unit testing with JUnit, and javascript unit testing with a browser. Since these are true unit tests of javascript code, it would be nice to integrate it into our JUnit testing cycles. Another benefit of testing javascript from within java is that we can use dynamically generated mocks to provide simulated collaborators - just like standard java tests can.

An alternative to using JsUnit and a browser, is to use Mozilla Rhino (http://www.mozilla.org/rhino/) to interpret the javascript from within Java. This should give you good confidence that the logic is implemented correctly. This allows for rapid feedback during your TDD sessions. No browser windows to pop up, nothing fancy to set up on the continuous integration side, and it's cross platform. And best of all, we can mock out any objects the script expects. Note that you should test your logic code here, I would recommend to keep the browser-specific code (stuff manipulating truly browser specific objects) tested in JsUnit.

Note that this route doesn't provide you with the standard objects that a browser would normally provide - no access to the document, etc. It would just be used for "logic" routines. I suggest having a split between logic routines, and ones which interact with the browser - and use JsUnit or WATIR/Selenium/PAMIE to test that the browser routines work properly.

For my javascript JUnit test, I've done the following:

protected void setUp() throws Exception {
super.setUp();
ctx = Context.enter();
scope = ctx.initStandardObjects(null);
}


protected void tearDown() throws Exception {
try
{
Context.exit();
}
finally
{
super.tearDown();
}
}


This ensures that the (thread local) javascript context is initialized/cleaned up properly.

You then wish to import the script under test into the context:

ctx.evaluateReader(scope, getReaderForResource("TestJavaScript.js"), "TestJavaScript.js", 0, null);

Get the Function placeholder for the function we will call:

Object functionRtnObj = scope.get("anyFunction", scope);
assertTrue(functionRtnObj instanceof Function);
Function functionObj = (Function) functionRtnObj;

Make the actual call with supplied parameters:

Object result = functionObj.call(ctx, scope, scope, new Integer[] {new Integer(1)});

Do some assertions on the return value:

assertNotNull(result);
assertEquals("anyReturnValue", result);

That's it!

NOTE: we cannot create javascript unit tests using JsUnit and run them from within java by using Rhino because it depends on various browser specific objects. An option (which I haven't verified yet) might be to write your tests in JsUnit, and use HtmlUnit (which uses Rhino for javascript) to simulate a browser. This way we can run the tests through a quick java system (suitable for a continuous integration system), and through various real browsers. All (or most - HtmlUnit is by no means complete) of the normal browser objects should be available. No mocks though :)

Enjoy!