Monday, May 08, 2006

Test Doubles (via Martin Fowler)

Martin Fowler writes "Gerard Meszaros is working on a book to capture patterns for using the various Xunit frameworks". This looks very interesting and I intend to peruse it more when I have free-time, but for now I'd just like to repeat the little snippet of definitions that Martin included.

Test Double is a generic term for any case where you replace a production object for testing purposes. There are various kinds of double that Gerard lists:
  • Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
  • Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an InMemoryDatabase is a good example).
  • Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.
  • Mocks are pre-programmed with expectations which form a specification of the calls they are expected to receive. They can throw an exception if they receive a call they don't expect and are checked during verification to ensure they got all the calls they were expecting.

Thursday, May 04, 2006

(Link) Presentation on the pretty parts of Javascript

I just discovered this presentation by Alex Russell of dojo fame, detailing Object Oriented Programming, Functional Programming and Aspect Oriented programming techniques in javascript. Well worth a glance.

Javacript Beans - Beanify

I'm going to write a couple of blog posts, about a tiny code library I've written, which I think quite nicely shows the beauty and flexibility of the javascript language, as well as being a very useful implementation of javabeans-like functionality in javascript.
Why would you want javabeans in javascript? Well for me, I needed a cross-platform way of being notified whenever an objects property is modified, previously I had classes with lots of methods that look like

this.setSize = function(s){
size = s;
signal(this, "actionChanged", "size", s);
};
The signal function is part of MochiKit 1.3's new Signal/Slot mechanism (very useful, I've been using it from cvs for quite a while now and don't know how i survived without it).
The first step in this process was to develop a method that generated the getters and setters for me.


function beanify(obj, props){
var properties = {};

for(var i=0; i<props.length; i++){
var propName = props[i].toString();
var getter = function(){
return properties[arguments.callee.propertyName];
};
getter.propertyName = props[i].toString();

var setter = function(o){
properties[arguments.callee.propertyName] = o;
};
setter.propertyName = props[i].toString();

obj["get"+props[i].charAt(0).toUpperCase()+props[i].substring(1)] = getter;
obj["set"+props[i].charAt(0).toUpperCase()+props[i].substring(1)] = setter;
}
}

It is a very simple bit of code, but quite elegant, it illustrates three very important concepts of javascript.

1. Classes and objects are open - This means that new methods can be added to objects and classess (prototypes) on the fly.
2. Closures can be used to create private variables - I want the properties array to be private, i.e. it can't be accessed from outside the generated methods. In javascript this is simple, I create a local variable in the outer function, this can be accessed by the inner functions (getter and setter) but not from anywhere else.
3. Functions are objects - The getter and setter functions also need to know the name of the variable they are getting and setting, this must be stored in a variable somewhere. I can't store it in the beanify function ie.

var getter = function(){
return properties[propName];
};

because the propName variable is passed by reference not value, so propName is modified every time the loop iterates - thus when the getter or setter is actually called, propName = props[props.length-1]. The solution is to attach a copy of the property name to the getter/setter function object. This solution isn't quite perfect as the property name is publicly accessible, but I'm sure this can be fixed easily.

Thats all for now, but in Part 2 I will show the full glory of the JSBeans class, including how I use it to create the property changed events I need, and how it can be used as a cross-platform replacement for the netscape/mozilla watch() function.