Friday 5 December 2008

How easy is it to validate the format of an email address

The other day I had to create an admin console for creating a user object which contained the usual fields,
  • username
  • forename
  • surename
  • email
etc.

When it came to setting up the active record object to ensure that the username, forename and surname are supplied I started spec'ing the behaviour. All was moving along well.

When it came to validating the format of the email address I realised this was something I'd not done this before. Off the top of my head an email address must
  • include only one '@'
  • not include spaces
There must be a lot more to it than that.
With a bit of help from google I found there was a helpful standard that specified exactly what is a valid email address. All of a sudden my nice task of creating a scaffold for a user object had grown to include 'implementing validation for email addresses' which was going to be slightly more than,

validates_presence_of :username, :forename, :surname


The folks in the team keep talking about Rails plugins for this, that and the other. Could there be some kind sole out there that has already solved this problem?

google 'rails plugin validate email format'

and there it is!

http://code.dunae.ca/validates_email_format_of.html
A plugin called validates_email_format_of by Alex Dunae.

There has got to be a catch, how complicated is it going to be to get into my codebase and make use of it?

Here is the user class before

class User
validates_presence_of :username, :forename, :surname
end

and here is the User class after

class User
validates_presence_of :username, :forename, :surname
validates_email_format_of :email
end


I'd a few failing tests sketched out to check the email validation....all of a sudden they all pass!

Job done.
Simple and elegant, what more could you ask for?

Wednesday 3 December 2008

Working With Rails

I've just started working with a new team on a Rails project. It seems very weird to be developing full time in Ruby after spending the last eight years where the main focus of the day job has been java development.

It is great to have all of these new things to learn in terms of rails, cucumber, rspec-rails and mysql. It is a little daunting being thrown that bit outside of my comfort zone with all this new technology at once even though I've been using ruby for the past 3 years.

I'll be sure to report back with all the interesting things I learn.

Saturday 17 May 2008

We've gone Groovy

When we started our latest project about 6 months ago I was banging on about using Groovy. Nobody was convinced or should I say interested.

On Thursday the Mighty Gus and myself went along to a presentation on Groovy. We came back thoroughly enthused and were desperate to use it day to day.

Rather than placing Groovy code directly into the application we thought it would be good to introduce the language in the test suite. This would help familiarise the team with the language before introducing Groovy to the actual web application ( that is if we chose to go ahead and continue using the language ).

All of the developers on the team are competent with Ruby and would keen to use it within a web app. Having a Java web app places a bit of a restriction on introducing Ruby into the app code. This is the major win for Groovy, it seamlessly integrates with the Java code!

The main aim for Thursday afternoon was to
  • get Groovy up and running within our development environment,
  • write a test case for new functionality
  • update the continuous build and try to have minimal impact on the teams local environments.

Getting Groovy up and running locally
Only two downloads were required.
  1. The Groovy compiler
  2. JetGroovy, the IntelliJ plugin
Then we pointed the plugin at the Groovy home and added the groovy-all.jar to the test module path.

At this point we could run groovy test cases against our java codebase!
When running 'All Tests' in IntelliJ it automatically picked up the groovy test case!


Writing a test case for new functionality
Gus and I were half way though some work prior to going to the presentation.
We took the old Java test case and cloned it into a groovy test case ( updated the file and classname to avoid clashes).

At this point we were running groovy tests!

Yet we weren't taking advantage of any of the Groovy-ness, it was simply a renamed Java class.
What Groovy features did we make use of?
  1. Remove semicolons ( as Ben described it, "the bald look" )
  2. Removing method brackets ( this only works in certain situations)
  3. Dropped types where they were not of value.
  4. Introduce groovy lists for those ugly mock objects to return.
  5. Replace the ugly mocks with some super-condensed stubs.
I should explain 4 & 5 above a bit more.
4: Due to the nature of some of our 'generic' interfaces that we were testing, the tests need to know about the 'generic' type. ( Does this sound like a contradiction to anyone else? )

For example:
We were testing a Spring Controller which adds the size of a list of items to the Model for display.
The list of items was retrieved from a Dao, which is injected into the Controller.
Standard practise on our project is to mock the Dao and, in the test, place expectations on the methods that will be called.

public class Controller
{
private Dao dao;

public Controller( Dao dao)
{
this.dao = dao;
}
public void handleRequest( HttpRequest request, HttpResponse response )
{
Map model = new HashMap();
model.put( "number_of_items", dao.getItems().size() );
return new ModelAndView( "viewname", model );
}
}

public class TestControllerJava extends MockObjectTestCase
{
public void testCorrectNumberOfItemsAreAddedToModel()
{
List items = Arrays.asList( new Item(), new Item(), new Item() );
Mock mockDao = mock( Dao.class )
Controller testee = new Controller( (Dao)mockDao.proxy() );

mockDao.expects( once() ).method( "getItems" ).will( returnValue( items ) );

ModelAndView actual = testee.handleRequest( null, null );
assertEquals( items.size(), actual.getModel().get( "number_of_items" );
}
}

Here nothing in the Controller is particularly interested in the type Item. It is only concerned about the number of Items.

Which brings us to introducing Groovy lists.

class TestControllerGroovy extends MockObjectTestCase
{
void testCorrectNumberOfItemsAreAddedToModel()
{
def items = ["one","two","three"]
Mock mockDao = mock( Dao.class )
Controller testee = new Controller( (Dao)mockDao.proxy() );

mockDao.expects( once() ).method( "getItems" ).will( returnValue( items ) );

ModelAndView actual = testee.handleRequest( null, null );
assertEquals( items.size(), actual.getModel().get( "number_of_items" );
}
}


In this example the differnce may not be much, but consider the situation where the construction of the Item object is complex and needs a number of params.

This brings us nicely to further explaination of item 5 above. ( Replace the ugly mocks with some super-condensed stubs.)


class TestControllerGroovy extends TestCase
{

void testCorrectNumberOfItemsAreAddedToModel()

{

def items = ["one","two","three"]

def dao = [getItems: { items }] as Dao

Controller testee = new Controller(
dao );

ModelAndView actual = testee.handleRequest( null, null );

assertEquals( items.size(), actual.getModel().get( "number_of_items" );

}

}


Here we have, line in Javascript, created a map instead of an actual typed object as the stub. We have satisfied just enough of the interface that we are interested in ( or that the source is interested in ).

The map is defined within the square brackets, the first item being the method call, then a colon, then a block ( which is defined in the curly brackets ) which will be executed when the method is called. You can have as many of these as you like, separated by commas. Another point to note is that, just like in Ruby, the result of the last statement executed will be returned by the method. Therefore there is no need to explicitly say {return items} as {items} will do perfectly well.

I'm not suggesting to use this as a rule, always aim for the clearest code/test possible rather than roping in as many new features of a language as possible.

The example above is a great deal simpler that the actual code and test we created on Thursday. It had 7 lists and 7 mock expectations and it looked absolutely hideous. It was so much nicer to see it condensed into 7 lines, however it felt really strange seeing so much functionality defined within 7 lines!

I suspect this is something we will get used to, it just felt weird.

Check in time - or is it?
How will this affect the other developers and the build box?

Our Team City build delegates to Ant. A quick look at the Groovy site gave some nice examples for compiling Groovy in Ant.

What we did forget to do was to add the groovy-all.jar to the ant classpath - D'oh.

We then updated the build box with the appropriate groovy install and jars and put together some info for the other developers about where to find the compiler and JetGroovy.

Job done.

I'll let you know how we get on!
WOOOO