Thursday, June 12, 2008

Why You SHOULD Have 100% Code Test Coverage

I recently wrote a post about the level of code coverage that I achieved on a project that I was working on.  Then I started seeing articles about how 100% code coverage is a fallacy, or how code coverage tools are "evil".  I disagree.

iStock_000003827645XSmall

Ok, before everyone kills me, let me explain.  I do agree to the following:

  • Code coverage numbers can be abused (just like a defect/bug count)
  • Code coverage is NOT and indicator of how well tested your code is
  • Code coverage number should never be used by themselves to draw any sort of conclusion about the code

Argument 1: It's Waste of Time

The first argument that I saw was that testing simple pieces of code such as simple getter/setter properties is a waste of time that can better used writing a unit test for a more complex piece of code.  So more bang for your buck.

You don't have to waste your time writing tests for simple getter/setter properties.  A good testing framework can take care of this for you with little or no work on your part.  NewtonSoft Utilities.NET contains a class that will dynamically test all of your properties.  Using this utility, you can write a single unit test that tests all of your properties on a class.  And this unit test can copied and pasted with one or two minor modifications to test the next class.  Elapsed time: 30 seconds to create class, write function and run test.

In addition, no unit test should ever be considered a waste of time.  A single unit test is meant to test a single scenario and that unit test will also ensure that chunk of code will always behave as expected in that scenario.  What starts as a simple getter/setter property may evolve to a more complex one and the unit tests written for that property will ensure that the evolution of that property does not sacrifice functionality without you know about it.

Argument 2: Trust Your Programming Language/Framework

Another argument against testing things such as simple getter/setter properties is that why would you not trust your programming language/framework/environment to perform a simple get or set operation?

Why would you trust your programming language/framework/environment?  Programming languages are software and thus can contain bugs too.  Now the likelihood that you will ever encounter such a bug is low, but why take the risk?  As long as you have a good testing framework as I stated above and unit testing your properties takes little or no time, then it is far better to catch the bug in unit tests than in production code.

More importantly, unit testing the simple pieces of code is not about not trusting your programming language but rather not trusting yourself.  I, and I'm sure most of you, have at one time or another fat-fingered something in code.  There are numerous ways to screw up on a simple property.  How about having the following?  It is very easy to do the following, especially with code-completion.  This is not really a bug you want making it into production code, especially if a single unit test would have exposed this.  And if the problem doesn't immediately stand out at you, then you've proved my point.  And now imagine this property inside of a class with other code and documentation.  Suddenly this bug because camouflaged and less easy to see with the naked eye.

public int Width
{
	get { return Width; }
	set { _width = value;}
}

Argument 3: Code Coverage Is Not An Indicator Of Code Quality

This argument is half true.  The true reason that code coverage can not be used as an indicator of how well the code is written is because code coverage only indicates that the individual lines were executed.  It does not indicate what combination of individual lines were executed.  In other words, it says nothing about code execution paths.

However, code coverage can help indicate how modularized the code is.  What?!  I said it helps indicate that.  If you have complex code, the quicker you are able to achieve 100% code coverage (or a high level of code coverage), the more modularized your code possibly is.  Very modular code means that the individual pieces of your code are smaller and less dependent on other pieces of code.  This in turn means that your unit tests will be smaller, more focused and require less setup.  Given all of that, the unit tests should be quicker to write.

In my previous post about code coverage, I stated that I employed IoC/DI and AOP and was able to achieve a high level of code coverage very quickly and every class was either 100% covered or 0% covered and the 0% covered classes were very small and contained "untestable" code.  The application had its complexities, yet I was able to achieve this code coverage scenario relatively quickly.  Analyzing the code showed that it was very modular.  TDD yields the same results.  Modular code with high code coverage.

Having modular code means that you should be able to write more unit tests quicker and more effective unit tests because they are more focused on smaller pieces of code.  This could lead to more quality code.  It is important to note that highly tested modular code does not guarantee quality.  But the chances of it are higher.

Conclusion

While it does not give you the world, aiming for 100% code coverage does help you write better software depending on the steps you take to achieve this high code coverage.  Code coverage in and of itself is not evil and the code coverage percentage does provide some useful insight when used in conjunction with other pieces of data about your code.

Just as with everything else, the quality of your code depends on the methodologies, techniques and technology that you use coupled with your development skill level.  Aiming for 100% code coverage is just another technique.

Aim high.  Never let your grasp outreach your goals.

Submit this story to DotNetKicks

Thursday, June 5, 2008

FeedBurner 404 Error

I recently encountered a 404 error when attempting to fetch one of my RSS feeds from FeedBurner.  I have a web application that requests the feed using an HttpWebRequest in .NET and then formats it and displays it on the page.  I could navigate to the feed just fine, but my web application stated that the connection could not be established because the server returned a 404-Not Found error.  This was working all the while, so something had to have changed somewhere (and it wasn't in the code since the code hasn't changed in a month according to source control).  Stepping through the code, I discovered that the URL that it was claiming it couldn't find was http://feedproxy.feedburner.com/....  The URL I was originally requesting was http://feeds.feedburner.com/..., so FeedBurner was redirecting my request for some reason.  Using Live HTTP Headers in Firefox, I could see that my browser was not receiving this redirect.

Turns out that when I make the HttpWebRequest, if I supplied a UserAgent, then I didn't get redirected to that feedproxy.feedburner.com address.  I've been meaning to go back in and supply a UserAgent anyway.  I'm not sure what the feedproxy.feedburner.com URL does or why it went down, but supplying a UserAgent seems to avoid the redirect.

Technorati Tags: ,,

Submit this story to DotNetKicks

Wednesday, June 4, 2008

Empty EventArgs

How many times have you written an event whose event handler just takes in a generic EventArgs object and when you raise that event you pass in new EventArgs()?  Turns out the EventArgs class has a static read-only instance field EventArgs.Empty that you can use so you don't have to instantiate a new copy of this class for no reason.  Microsoft's documentation says that this instance is the equivalent of calling the constructor.  Again the benefit is that this instance is already created.

To quote a colleague, "Think of the performance boost we’ll get!"  I'm fairly certain he was being sarcastic.

public event EventHandler<EventArgs> MyEvent;

protected void OnMyEvent(EventArgs e)
{
	EventHandler<EventArgs> hnd = MyEvent;
	if (hnd != null) hnd(this, e);
}

public void DoSomething()
{
	OnMyEvent(EventArgs.Empty);
}

Technorati Tags:

Submit this story to DotNetKicks

Tuesday, June 3, 2008

Unit Testing Enum Value Support

Let's say you have a function that takes in an enum value or uses an enum value fetched from some other source (a private class field, a property of an object passed in, etc.).  If a value is added to that enum, how do you write a unit test for that function so that it catches that something has to be added to your function to support that enum (or at minimum, you need to check to see if you have to add anything to the function to support it).

I've already discussed how to put in a check for making sure that your function will bomb if an unsupported enum value is passed in in my "Unit Testing Switch Statements" post.  This takes it one step further to ensure that your unit tests catch the bombing of this function if a new enum value is added so that this bombing doesn't occur in production or even in QA's testing.

Below I have an example of this situation.  I apologize for the crude example but it gets the point across on how to test this situation.

public enum CalculatorOperations
{
	Add,
	Subtract
}

public static class Calculator
{
	public static int PerformOperation(CalculatorOperations operation, int a, int b)
	{
		Check.Invariant(operation == CalculatorOperations.Add ||
		                operation == CalculatorOperations.Subtract,
		                string.Format("{0} is not a supported CalculatorOperations value.", operation));

		int result = 0;
		switch(operation)
		{
			case CalculatorOperations.Add:
				result = a + b;
				break;
			case CalculatorOperations.Subtract:
				result = a - b;
				break;
		}

		return result;
	}
}

[TestFixture]
public class Calculator_Tester
{
	[Test(Description = "Tests for unsupported CalculatorOptions values.")]
	public void Test01()
	{
		Type enumType = typeof (CalculatorOperations);
		foreach (FieldInfo field in enumType.GetFields(BindingFlags.Static | BindingFlags.Public))
		{
			CalculatorOperations operation = (CalculatorOperations) field.GetValue(null);
			Calculator.PerformOperation(operation, 1, 1);
		}
	}
}

Now if I add Multiply and Divide to the CalculatorOperations enum, my unit test will fail because Calculator.PerformOperation will throw an exception on the unsupported value.

Remember, "do nothing" is still an intended behavior.  So even if you don't explicitly use an enum value in a function, you need to have it in your "supported enum values" list to ensure that that value allows the function to perform the way it is intended to.  The added benefit of this technique is that it also catches scenarios that you haven't tested for.  Even if PerformOperation is going to return 0 (do nothing in the switch statement) when Multiply or Divide are passed in, then you need to write unit tests for those values and then add those enum values to the function's "supported enum values" list.

Technorati Tags: ,

Submit this story to DotNetKicks