How To: Get 100% code coverage with C# Switch Statements

Recently I started looking at 100% code coverage for my unit tests. Although, this is a good thing to achieve, it could become a daunting  task specially if you have foreach or switch statements. Let me illustrate the problem using the switch statement. Here is some sample code of a class VehicleType with a lone method PrintVehicle which accepts an enum VehicleTypes and prints the appropriate vehicle name using switch statement.

    1: public class VehicleType
    2:     {
    3:         public void PrintVechicle(VehicleTypes vt)
    4:         {
    5:             
    6:             switch (vt)
    7:             {
    8:                 case VehicleTypes.Bicycle:
    9:                     Console.WriteLine("Bicycle");
   10:                     break;
   11:                 case VehicleTypes.Car:
   12:                     Console.WriteLine("Car");
   13:                     break;
   14:                 case VehicleTypes.Motorcycle:
   15:                     Console.WriteLine("Motorcycle");
   16:                     break;
   17:                 case VehicleTypes.Scooter:
   18:                     Console.WriteLine("Scooter");
   19:                     break;
   20:                 case VehicleTypes.Truck:
   21:                     Console.WriteLine("Truck");
   22:                     break;
   23:             }
   24:         }
   25:         public enum VehicleTypes
   26:         {
   27:             Bicycle = 0,
   28:             Scooter = 1,
   29:             Motorcycle = 2,
   30:             Car = 3,
   31:             Truck = 4,
   32:         }
   33:     }

 

The following is a test method for the PrintVehicle method, as you see it has covers all the VehicleTypes.

 

    1: /// <summary>
    2: ///A test for PrintVechicle
    3: ///</summary>
    4: [TestMethod()]
    5: public void PrintVechicleTest()
    6: {
    7:     VehicleType target = new VehicleType(); 
    8:     target.PrintVechicle(VehicleType.VehicleTypes.Bicycle);
    9:     target.PrintVechicle(VehicleType.VehicleTypes.Car);
   10:     target.PrintVechicle(VehicleType.VehicleTypes.Motorcycle);
   11:     target.PrintVechicle(VehicleType.VehicleTypes.Scooter);
   12:     target.PrintVechicle(VehicleType.VehicleTypes.Truck);
   13: }

 

You would expect code coverage of 100% as we test all the cases for switch statement. But, the code coverage shows only 92.31% covered and 1 block of code missing as shown below.

 

codecoverage

Lets look at the code and see what was covered in the test. Amazingly everything seems to be covered so which block is not being tested. It turns out that compiler adds some additional code at the IL level during debug mode which is responsible for this erroneous behavior. Similar problem exists for foreach statement, we can fix this by using for statements. But, for statement poses different problem as the alternative is complex if else conditions. Lets look at some alternatives to fix switch statement issue.

image

In this case we add a new enum value which we will not handle in the switch statement. For example we add a new enum value "None" to the VehicleTypes and include that in our test case without handling the new value in the switch statement. Please note that this is a breaking change when it comes to code compatibility, specially if you are writing a framework.

 

    1: public enum VehicleTypes
    2: {
    3:     Bicycle = 0,
    4:     Scooter = 1,
    5:     Motorcycle = 2,
    6:     Car = 3,
    7:     Truck = 4,
    8:     None=5
    9: }
   10:  
   11: /// <summary>
   12: ///A test for PrintVechicle
   13: ///</summary>
   14: [TestMethod()]
   15: public void PrintVechicleTest()
   16: {
   17:     VehicleType target = new VehicleType(); 
   18:     target.PrintVechicle(VehicleType.VehicleTypes.Bicycle);
   19:     target.PrintVechicle(VehicleType.VehicleTypes.Car);
   20:     target.PrintVechicle(VehicleType.VehicleTypes.Motorcycle);
   21:     target.PrintVechicle(VehicleType.VehicleTypes.Scooter);
   22:     target.PrintVechicle(VehicleType.VehicleTypes.Truck);
   23:     target.PrintVechicle(VehicleType.VehicleTypes.None);
   24: }

Now run the tests and check the results, amazingly we have 100% code coverage. I know that this may not work for all switch statement problems but at least gives you an option to achieve that perfect 100% coverage.

Some MSDN links talking about IL code generated for switch statement.

https://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3527731&SiteID=1

Thanks

Anil Revuru