When I first began to adopt the Unit testing mindset, I looked at it as a chore. It’s pretty obvious how non-motivating the thought of going back to a project to write tests can be. So I eventually gave up on the idea of testing and just hack-tested as I went along programming, expecting the things I tested at the beginning of the project to just “work” as I went along. The flaw with this (obviously) is that once you get further into a project, you’ll inevitably make changes along the way that affect things you’ve already “tested,” and a series of breakages will occur that you’ll spend hours and hours debugging only to have that moment of “oh yeah” later. After several years of this nightmare, I decided to look at testing again – this time with a fresh look on when to test and what to test.

I’ve been using Ruby on Rails now for several years and it’s made me an infinitely happier programmer. Besides being built on a cool language like Ruby, which lets us Ruby programmers do all sorts of cool things, Rails has a plethora of built-in testing methods that make testing so easy “you’d be stupid for not doing it.” But that still leaves us with the same problem question when we’re done with a project: “well it’s done now, do I have to write tests?”

It dawned on me sometime back when I started “testing first” that this problem is much like the difference between Math class (which I enjoyed) and History/English class (which I abhored). The difference between the two was obvious to me (in my mind). In Math, you could easily know you had the right answer because you could check it. History? Good luck. (I once scored 4 out of 50 on a scan-tron history test – yeah, 4 out of 50). In fact, in History we were even allowed to argue with the teacher about the accuracy of the test (which, in the end only gained me 2-3 points on my miserable score).

Most programmers write code like it’s History.

Don’t believe me? What’s x in 5x = 15? Well, if we do the algebra we come up with 3 – but how can we be sure it’s 3? We test! If we put 3 in for x, we come up with 15. Great, so we got the answer right – and we know it’s right. (If I wanted to be really cute about this example, our test ”= 15” is already written for us.)

We can take this example a bit further to programming. Think about all the assumptions you make when you sit down to write code. In the process of programming a project, you’re likely to make thousands of assumptions each time you code. Things like “this will never be nil” or “this will always create a record.” All those little assumptions should first be written down in your tests so they fail. Not only does this help you keep track of your assumptions and make sure they are always valid, it also helps maintain a todo list for all those things you “plan to get to later” and never do. Interruptions have to be a major cause of bugs.

Not only are the assumptions fresh in your mind when you test first, all the cases are as well. It’s usually not so easy as 5x = 15, there’s usually a lot more scenarios you need to consider. Sure enough, when testing first it’s significantly easier to consider and record those cases (especially edge cases) as tests, then make sure they all pass now and forever.

So test first, it’s better than History.

More advanced topics regarding the model_formatter plugin for Rails.

In Part 1, we learned about setting up the model_formatter to format and un-format attributes as they came in and out of the model. We saw how you could use some simple methods formatted_weight and formatted_weight= to get and set the formatted attributes. In this article, I’ll show you how to use more of the generated methods for more advanced usage.

Update – r5826 changes the default names of the formatters to use the format attribute name. (article revised)

Read the rest of this entry

How to get up and running with the model_formatter plugin for Rails.

I’m in the middle of a very large project which I can’t talk too much about until it’s done, suffice to say we’ve got lots of database columns that need to be formatted/un-formatted. View helpers are great for formatting things on the way out, but what happens when users need to enter that data in the same format, or in an auto-detected format?

Updated 07/25/2008 – New repository on github

Read the rest of this entry