Fixing bugs in untested code

When you’ve got an application that has little or no test coverage it can be quite daunting making changes. What if you alter X and it breaks Y? Without running through the entire app by hand how will you know what you’ve broken?

Well you won’t.

Even worse, what if your client reports a bug in that application? That makes things even worse doesn’t it?

No. It’s actually an opportunity. Because even if your boss thinks “testing is a great idea, we’ll start on the next project when we’ve got more time”, a bug fix is one of those things where the time to fix varies. So take advantage of that.

Start by writing a test that reproduces some functionality in the same area that you know works.

This won’t be easy. You need to get the database into the correct state, set up the session correctly. To save you some time, try using an object factory – with the correct configuration you can concentrate on creating just the models you need without having to fill the entire database with test data.

Take a look at the code you are testing as you are writing the tests. But make sure your test checks the outcomes of that code, not the implementation – when using mocks it’s pretty easy to end up effectively rewriting the real code as a series of should_receive(:something) calls. Which looks great until you come to refactor, at which point it becomes a nightmare.

Get your test to pass. Remember this is a feature that works so it shouldn’t be that hard to get it to pass. And you are building some important foundations as you are setting up a configuration for your object factory a model at a time.

Once you’ve got the first test working, prove that it’s doing what it’s supposed to be doing. Comment out its of the implementation and watch it fail. If it doesn’t fail then you’ve got a problem – your test is testing something other than that particular implementation.

Now we’ve got a test that really checks your existing code. I like to add another test that checks the error handling in that existing code as well (there is error handling in your existing code isn’t there?) Follow the same process as before – test the outcomes (probably catching an exception if you’re at the model level, probably looking for a particular redirect and flash message at the controller level), and then prove that it works by commenting code out. Hopefully this should be pretty quick to write as most of the hard work was done when setting up the original test.

And finally we can get to the meat of it. Write a test that reproduces your bug (that is, your test exercises your app in the way expected and your app should fail). Again, most of your setup work should already be done, so it shouldn’t take too long. Now run the test and watch it fail. If it doesn’t fail then your test isn’t right.

After all of this, we are finally in a position to fix the bug.

Your test should prove that it’s been fixed. And prove that the bug won’t reappear in a future version. But you’ve also taken an important first step to wrapping your application in tests, making your life easier in future.

Tags: , , , ,

This entry was posted on Wednesday, May 6th, 2009 at 8:54 pm and is filed under Ruby on Rails and Software Development, Writing Reliable, Bug-Free Code. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.

Comments are closed.