Posted on May 31st, 2008

Picture yourself on a warm beach – margarita (or Shirley Temple) in one hand, laptop in the other, test-driving the next big thing. That’s what life is like every day for those of us in the great Sunshine State.

Or not. But we still have a lot to offer, and since many of the agile principles are being adopted more and more, there are corresponding user groups and conferences coming up. So this evening I relaunched Agile Florida to start to pull together the various agile user groups, code camps and conferences going on around our great state. This was actually an idea several of us kicked around at a BoF session at Agile 2006, but is just now finally coming to fruition.

If you are in Florida and know of user group meetings coming up, or want to be able to publish them, give me a shout and I’ll get you set up to be able to do just that. And if you know of good Florida Agile Blogs, please let me know!

2 Comments


Posted on May 28th, 2008

We’ve been creating several Java Beans that have an imperative need to have both equals and hashCode working correctly. To do this, we started off writing a series of test cases which made sure that for every field we exposed that the objects were / were not equal based on if the field was set, and that the field was taken into account as part of the hashCode calculation. After doing two of these, I figured there had to be a better way, and after some research, ended up writing a BeanTestCase class which exposes an assertMeetsEqualsContract method and an assertMeetsHashCodeContract method. Note that while there are projects out there (like Assertion Extensions for JUnit) that have assertions for equals and hashCode, they don’t actually walk the fields of the objects and test the various scenarios of changing each field.

After I had written this, I applied it to classes we already had unit tests for around equals and hashCode – and immediately found a bug in one of the classes where we missed a field. That paid for itself right away. ;)

Being that I’m just getting back into the Java world, if there are better ways, please let me know!

7 Comments


Posted on May 26th, 2008

In a recent post I talked about being pretty disappointed with Serena Dimensions and its lack of strictly command line options. It appeared that no matter what you did, you still had to enter your credentials through the GUI pop-up box.

After reading through the 380+page command-line reference, I’m happy to report that I was wrong. The program is called dmcli.exe and takes in a variety of parameters. What worked for us was:

|C|dmcli.exe -user USER -pass PASS -host HOST -dbname DBNAME -dsn DSN -cmd FWI PROJECT:REV /USER_DIRECTORY=\"${srcroot}\" /NOTOUCH /OVERWRITE|EC|

where USER, PASS, HOST, DBNAME, SDN PROJECT, REV and srcroot are all whatever you would use. Right now I just have it forcing a build every hour in CruiseControl.NET, but eventually I’ll write a wrapper to actually be able to check the repository for changes (assuming we continue to stick with Serena).

Thanks to the people in my last post who pointed out the command line guide.

3 Comments


Posted on May 26th, 2008

Recently I’ve been working on a project using Java and a technology called Gigaspaces. Being back in the Java world has been interesting, but thankfully many of the tools and approaches are similar.

One aspect of our application (Ok, many, but we’ll pick one) is responsible for retrieving and storing information to a database. To make it clearer, let’s say that we are working with user information. Our service is responsible for:

  • Finding a user based on their username
  • Finding a user based on their unique identifier
  • Finding a related user based on a different user
  • Creating a user
  • Update a user

With the Gigaspaces technology, we are basically using a big Enterprise Service Bus. So, for one of our other services to find a user, they create a UserRequest and populate it with a user object and an action – Create, Request, Update, or FindRelated. This gets mapped to our UserService, which then handles the request and puts the UserRequest back on the Bus with a state of complete. This request then gets passed back to the originator.

So, for us, that basically means we have a UserRequestProcessor which has to expose a method to handle incoming requests. It returns a UserRequest object, and Gigaspaces knows how to map that. In other words, we can write our code to basically ignore Gigaspaces from a developer test perspective.

The basic architecture that we came up with was to have the UserRequestProcessor delegate calls to a UserDAO which would then in turn do the data access via Hibernate mappings. This lets us write both interaction-based tests like:

public void testProcessorCallsRequestMethodOfDaoForRequestAction() {
  User user = new User(VALID_USERNAME, VALID_CONTEXT);
  UserRequest request = new UserRequest(user, UserAction.REQUEST);
  MockUserRequestProcessor processor = new MockUserRequestProcessor();
  UserRequest response = processor.processUserRequest(request);
  assertTrue(((MockUserRequestDAO)processor.getDataAccess()).requestIdentityCalled);
}

and more standard tests like:

public void testProcessorUpdatesRequestWithReturnedUserIdAndReturnsItForRequestActionWhenFound() {
  User user = new User(VALID_USERNAME, VALID_CONTEXT);
  UserRequest request = new UserRequest(user, UserAction.REQUEST);
  MockUserRequestProcessor processor = new MockUserRequestProcessor();
  UserRequest response = processor.processUserRequest(request);
  assertEquals(VALID_USER_ID, response.getUser().getUserId());
}

The magic is the getDataAccess() method of the UserRequestProcessor, a getSessionFactory() method of the UserDAO all coupled with Hibernate’s ability for us to override properties.

Let’s look at a simple method. In the UserDAO, there is a method called requestUser which takes in a User object, and returns the User object populate with the correct Username and Context for the given User ID. Thanks to Hibernate, it looks something like:

public User requestUser(User user) {
  Session session = getSessionFactory().openSession();
  User returnUser = new NullUser();
  try {
    returnUser = (User)session.get(User.class, user.getUserId());
  } finally {
    session.close();
  }

  return returnUser;
}

Now, this is a real live DAO, which wants a real live connection to a database. It is able to do its magic because of a real, live Hibernate mapping file. But I want to be able to drive the development and design of it using tests like:

public void testUserWithValidIdLoadsUsernameAndContext() {
 
}

How do I do that in a way that doesn’t take 45 seconds for the test suite to run, and allows me to reset the environment? The test actually looks like:

public void testUserWithValidIdLoadsUsernameAndContext() {
  UserDAO dao = new InMemoryUserDAO();
  User user = new User();
  user.setUserId(VALID_USER_ID);
  User result = dao.requestUser(user);
  assertEquals(VALID_USERNAME, result.getUserName());
  assertEquals(VALID_CONTEXT, result.getContext());
}

The magic is in the InMemoryUserDAO class. It is an inner class of my UserDAOTest class and overrides the getSessionFactory to return a connection to an in-memory database. But it does something else important as well, as we’ll see in a second:

protected class InMemoryIdentityDAO extends IdentityDAO {
  private SessionFactory factory = null;
  protected SessionFactory getSessionFactory() {
    if(factory == null) {
      factory = new Configuration()
          .configure() //pull defaults from hibernate.cfg.xml
          .setProperty("hibernate.connection.url", "jdbc:"hsqldb:mem:test_db");
          //override other db properties like driver and dialect
          .buildSessionFactory();
    }
    return factory;
  }
}

The first thing we do is load the same hibernate.cfg.xml file that our production classes use. This is important because it makes sure that any class mappings or properties we’ve set in there will be the exact same for our test classes. In other solutions I had seen something similar, but they either defined a special configuration file for testing, or used Hibernate’s methods to specify the class mappings in the test classes. Using this method, the only thing we override is the connection to the database, leaving everything else intact.

So, now in my test setup, I can spin up an in-memory database, populate it with the data, and make sure that I can use TDD to build my data access classes. And thanks to Gigaspaces for designing a product where I can build my classes and business logic without having to shove bunches of your code and objects in it.

2 Comments