Introducing Bob

March 2nd, 2006

Bob The BuilderBob is our build server - just like the children's TV character, he spends all day building stuff. Bob has to be one of the most beneficial improvement projects we've taken on at Ephox in quite some time. Every build of our key products that we ship both as full releases and hot fix patches are built by Bob. He even uploads them to the web server when told to make them available to clients.

That means two things, firstly and most importantly - we never ship a build that doesn't pass every single test. We can't, Bob just won't allow it (he's got the highest of ethics). Combine that with a policy of never checking anything in without automated tests (we're just starting to adopt test driven development, we've been doing automated testing for quite a while) and regressions are almost a thing of the past. Every so often we get a regression slip through because someone didn't write a unit test or because we just couldn't work out a way to test it (GUI code is particularly problematic, as are third party libraries that weren't designed with testing in mind). Even so, the improvements have been pretty dramatic. Hopefully the addition of test driven development will completely eliminate regressions once we get good at it.

The other advantage though is that it saves developers time, particularly when they're doing support. There's no need to sit and wait for all the tests to run, leave the heavy lifting to Bob. No need to tie up your machine doing the build and packaging (my gosh, docbook takes a long time to process all our documentation) - just let Bob do it. The fact that you can go to a website and upload the new build in just a few clicks sure beats manually using an FTP client too.

Sustainable Pace != 40 Hour Week

March 2nd, 2006

One of the tenets of XP is that you work at a sustainable pace. Mostly that means that you don't work such long hours that your brain turns to mush and you start churning out bad code, however there is more too it.

Working at a sustainable pace also means knowing when to take a break from a task. After weeks of slogging away at replacing this 3rd party library - constantly making progress and getting small wins from each acceptance test we got to pass - this afternoon both Doug and I seemed to have stopped caring as much as we should, so we took the afternoon off of that project and went and caught up on the other things we needed to do. When we return to working on it we should be refreshed and able to approach the problems with a more open, creative mind and thus write better code.

That's the theory anyway, we'll see how it pans out.

Acceptance Test Driven Development

March 2nd, 2006

Doug and I are currently busy replacing a third party library which we've used in our product for quite some time. Thus, the first thing we need to do is create a new component which behaves in exactly the same manner as the original component. Once we have that we can start adjusting the code to add features and work in the way we really want.

To ensure we get an exactly compatible replacement, we started out by creating a suite of automated acceptance tests against the original implementation and they all passed.  Then we removed the third party library and they all failed. From there we could gradually begin building our new component by attempting to make each acceptance test pass - one at a time.

It turns out, this is a very effective way to work. We have high-level acceptance tests which give us our overall direction. We pick one of them that is failing to work on and start trying to narrow down why it's failing by writing a integration test that gives the same error but is more narrowly focussed.  From there we can write a unit test that fails for a very specific, known reason. Then we fix it and move back up. The whole process winds up being:

  1. Pick a failing acceptance test.
  2. Identify why it fails more narrowly by writing an integration test.
  3. Identify why the integration test fails by writing a unit test.
  4. Make the unit test pass.
  5. Run the unit tests, if any fail go back to step 4.
  6. Run the integration tests, if any fail go back to step 3.
  7. Run the acceptance tests, if our acceptance test (or one that previously passed) fails go back to step 2.
  8. Pick another acceptance test or if there aren't any failing tests we're done.

The biggest advantage to this process is that you can ensure that you're heading in the right direction. You can always ask yourself - does the unit test I'm writing get me closer to making the integration tests pass and does this integration test get me closer to making the acceptance test pass.

It seems to me that you should ideally always have the acceptance tests written for a user story before you start working on it - even if the first step is to sit down with the customer and write the acceptance tests. How else do you know that you did the right thing for the story?