Archive for the ‘Uncategorized’ Category

Acceptance Testing - XPToronto

Friday, December 16th, 2005

At the last XP Toronto we had a series of ‘Lightning Talks’. Basically 5 of us gave presentations on topics associated with TDD, each of 5 minutes, and followed with 15 minutes worth of discussion.

My contribution was this talk on Acceptance Testing. It is a summary of what I think are the important trends and tools in approaching this topic.

XPToronto - Acceptance Testing Presentation (PDF)

The format is inspired by the now famous Identity 2.0 keynote given by Dick Hardt at OSCON. It was an interesting experience, and people said that they found the presentation style useful.

This style seems to lend itself well to a narrative kind of presentation, so mine became a bit of a story about the history of and approaches to Acceptance Testing, sort of a starting point for the conversation rather than a set of bullet pointed assertions. This is particularly good for a lightning talk I think in that we don’t have much time anyway. I’m also not a fan of the bullet point anyway, so it was a muuch better fit for the way I like to present.

There are some differences to a normal presentation though:

  • The narrative can’t be interrupted - there is no place to pause and ask questions, and no way to go off on a tangent if the audience wants to pursue a different trail.

  • The slides may not provide a useful reference for the participants. I am in two minds on this one - I think that pointers to more information are probably better than bullet point assertions anyway

  • The medium may dilute the message. This is a problem with slideware in general, and it may actually be worse with this style until people get used to it. But I don’t know if this will be the case or not - the visual nature of the points may actually reinforce them and make it easier to recall parts of the argument. For example after the presentation a few people said that they liked the ‘brick wall separating the testers from the devs’ in slide 14 and 52, and maybe that image will come to mind next time they are in a meeting between the two groups?

Over all, I like the approach. I try to avoid slideware in general, and when I have used it I tend to a few slides, maybe some photos and lots of talking over bullet points. So I guess it is a good fit for me.

Q: When is an interface not an interface?

Friday, August 27th, 2004

A: When you can’t load it into the JVM without it hitting the DB

I am working on a large and somewhat aged app that has an interesting pattern.

Our services are Singletons (yes, I know, Singletons are Evil(TM) ) are implemented like this:

public interface Foo {
	public static final Foo INSTANCE = (Foo) Plugins.load(Foo.class);
	void doSomething();
}

The Plugin class statically initialises the instance by looking it up in a Properties file, something like this:

public class Foo {
	public static Object load(Class clazz) {
		String implClassName = getProperty(clazz.getName());
		try {
			Class implClass = Class.forName(implClassName);
			return implClass.newInstance();
		}
		catch(Exception ex) {
			logger.log("Could not load class " + implClassName, ex);
		}
	}
}

The properties file looks something like:

#interface=impl
com.demo.Foo=com.demo.impl.AConcreteFoo

The idea is that you can change the services depending on the location, server, whether you’re doing tests etc. So far, so nice.

But there’s a problem. Actually a few.

We also have a class that loads codes from a db table - through a statically loaded plugin. So what happens if I do something like:

public void testSomethingThatUsesAFoo() {
	Mock mockFoo = mock(Foo.class);
	...
}

Well Foo’s class is loaded by the classloader. It goes off and runs all the static initializers. And one of those calls into another service, static loaded and initialized, which loads the database, reads in all the codes, etc. so before you know it, just by importing an Interface, you have a test that requires the real database to be present. You can’t run the unit tests without a db, you can’t take your laptop home and do some refactoring. Nasty.

Worse is the fact that the error that is thrown by the plugin loader is obscured by a zillion ClassNotFoundExceptions, since the Plugin load failure, being in a static initializer, means the JVM cannot load the class.

Also since the exception is not centrally caught, it is also not possible to know when the system is in a fully configured and running state - there may be a Plugin that will not load until daily processing runs at 3AM next Wednesday - at which point that component fails in an isolated and undetected way. So the system keeps running while part of it is completely broken. Again - ouch.

From a testability standpoint, since the INSTANCE is defined as public static final, we can’t swap in a different implementation during test without running the tests in a different VM, with a different plugins.properties. Fine (in fact desirable) for Integration tests, but a real pain for unit tests.

So what’s the solution? We could just make each of the Foo users directly call (Foo) Plugins.load(Foo.class), but that doesn’t really help - it still means that the loading of services is dependent on random (or at least obscure) factors such as the order of class loading and static initialization. And it still doesn’t solve the random future failures problem.

The solution we have chosen is to move to a ServiceLocator pattern, backed by PicoContainer (Dependency Injection). We have a ready built pico configuration file in the properties file described above - basically the pico code to set the system up boils down to:

for each property in plugins.properties {
        pico.register( Class.forName(property.name), Class.forName(property.value) );
}
pico.start();

We will also be turning static initializers in the implementation classes into start() methods and externalizing their dependencies via their constructors.

Should be interesting.

what to do when your ISP deletes your weblog

Thursday, March 25th, 2004

Last week my ISP deleted my weblog.

I had asked them to downgrade my account from an ADSL account to something cheaper while I am in India. So they did, and in the process deleted the cgi space and MySql database that was hosting the weblog. Partly it is my fault, since (a) I didn’t keep my own backup and (b) I didn’t spell out for them in big block letters : DO NOT REMOVE THE 2 1/2 YEARS WORTH OF CONTENT. You’d think they might notice that it existed before going ahead and deleting it without a backup though. After all, even windows has an “Are you sure”.

So there I was with no backup of quite a lot of personal and professional thoughts and memories.

Fortunately Google has a really cool feature that allows you to see the latest cached version of any site in their index. As you can see if you do this query they archive quite a lot of stuff - my whole site included!

So a few days and lines of ruby later, I now have a newly retrieved webblog, hosted courtesy of my friend Damian Murphy.

Needless to say, I am also writing a script to regularly back it up…