Thursday, August 20, 2009

Why Test Driven Bug Fixing is Better #tdd #struts

Its often difficult to convince developers that aren’t doing Test Driven Development (TDD) that its worth the little bit of extra effort to write failing tests first before touching the code.  Most times, the dissenters complain about tight timelines and lack of end user benefit to ‘be bothered’ with it.

Although I am relatively new to TDD, I’ve adopted the method in every aspect of code development I can think of…especially bug fixing.

A Case Study

This is an actual example where I used TDD to fix a bug (the names have been changed to protect the ..um.. innocent).

QA reports a bug in newly developed software.  In this case, the application is a struts web application and there is a radio button on a form that doesn’t have a default set; the analyst believes that it should be set to value ‘x’ by default.

The radio button is backed by a form bean class with the property ‘theRadioOption’ in the class MyFormBean which is scoped to the request for the struts action in question.

public class MyFormBean extends ActionForm
{
	private string theRadioOption;
	public String getTheRadioOption(){
		return theRadioOption;
	}
	public void setTheRadioOption(String value){
		theRadioOption = value;
	}
}

Given this snapshot of information, many experienced struts developers would say “OK, so I’ll go and set the default value in the bean…its one line of code, no need for a test.”


Before touching the code however, I created a test by extending MockStrutsTestCase and coded a very simple test:

public class FormActionTest extends MockStrutsTestCase
{
	public void testFormDefaults()
	{
		setRequestPathInfo("/GetForm.do");
		actionPerform();
		final MyFormBean form = (MyFormBean) getActionForm();
		assertEquals("Wrong Default","x", form.getTheRadioOption());
	}
}

Running the test, of course, it fails…perfect…now to fix the code.

private string theRadioOption = "x";

There, that was easy, now before we build the application and deploy the thing, I run the test again to see if it indeed passes.  Surprisingly, it fails…so much for my “one line of code.”


Upon further examination, I looked in the action class that forwards to the web page.  What I found was that the developer that made the form was explicitly clearing the values in the form by setting the property to null.  My little ‘fix’ wasn’t seeing the light of day because the action was ‘undoing’ my default.

public ActionForward execute(ActionMapping mapping, ActionForm form, ...etc){
	final MyActionform myForm = (MyActionForm) form;
	form.setTheRadioOption(null);
	return mapping.findForward("SHOWFORM");
}

The real fix is to get rid of the explicit set to null in the action class or set it to the desired default instead of null.  After setting the default in the action and running my test again I can then see that the test passes.


This test becomes part of the project now and is run during the build process every night…the issue will never return undetected.  How much time did I save here?  Developer builds and deploys only once instead of two or three times, QA didn’t have to re-open the bug and therefore test the feature three times instead of two, the next developer didn’t have to ask “what should this be set to by default anyway” since it is well documented in the test.


My question is how can you justify NOT putting in the little extra effort to do Test Driven Bug Fixing?

No comments: