Practical approach to Unit Testing

This article explains some key approaches that you would consider when writing Unit Tests. 

As developers most of us write Unit Tests and we all know what is a Unit Test. Some may have slightly different opinions, but it is actually a programmatic verification of a single method/unit to ensure it behaves as expected. The reason I explain this because some developers still refers to a Unit is a component, assembly, or a module. When to comes to the term Unit Testing, you really testing a sensible testable unit of your software, and anything bigger than that would considered to be more of a integration testing. 

Benefits

Lets get real and discuss some of the benefits. I want to be more practical, and leave the MSDN Unit Testing benefits behind.

As a developer when you decide to write Unit Tests, do you ask the question from yourself, why I’m really writing these Unit Tests? Some of you answer Yes, and some of you say No.

Answer No, is simply because not knowing what you do, or because everyone else write Unit Tests. If your answer is Yes, that’s great, and you really consider the pros and cons of having Unit Tests.

All these benefits can be categorized into 3 main areas.

1.       Quality.

2.       Design.

3.       Cost benefits.

 

Lets talk about these areas briefly. 

The quality that provides by the Unit Tests can be many ways. It assists developing testable code. With TDD, the method/function that you write against a Unit Test, is well defined, and has a single responsibility. Unit Tests it self provide a valuable documentation to the project.  Less bugs will be introduced, also fixing bugs will be lot easier. As a developer you will have a great confidence on your system. 

If you practice TDD, you know Unit Test allows you to design a specific behaviour within your method. For example with TDD, you write your test first, make it fails, and then based on your test you write the method to ensure that your test passes. The result of this is basically designing a specific behaviour within your method. The other aspect of the Design is, when you design your system, you will also consider your functional requirements. Because one of the things that you need to ensure when you design your system is that your functional requirements have been met. Your Unit Tests are based on these functional requirements. I will discuss this in more detail in “Selective Unit Testing” section. 

We would love to develop a perfect system. But in reality, that is not always the case. Worse and the painful thing is some time projects are over the budget. This could be due to number of factors. One of the most common issues associated with the project cost is unexpected work at the end of the development cycle. This could be due to the number of bugs that have been raised during system testing. The number of iterations between the development and system testing cycles seems never ending due to the amount of bugs been raised. This can be due to poor system design, and or un-testable code. 

As you can see here, the number of defects you find is high during the development and the cost to fix those defects is relatively low when comparing to further stage of project life cycle. This is why the Unit Tests are important to ensure that we introduce fewer bugs during the development so the cost to fix those bugs are negligible at the later stage of the project cycle.

Selective Unit Testing

Writing “Unit Tests” is a good thing. Writing bad Unit Tests and/or unnecessary Unit Tests can lead to considerably high maintenance cost to your overall project. Do you believe on statements such as

We should aim for 100% code coverage”, “Any Unit Test is better than none”, or “Our main priority is the Unit Testing”?. All these statements do not add much value at all. These are some examples of expressing the way of the excitement, which causes by the Unit Testing

Few years ago we hired a developer to one of our projects. He is very keen on Unit Testing and he spent lot of time writing and managing Unit Tests. At the end our project was over the budget, and not what we really expected. If he decided what is really important, and write only the necessary Unit Tests, it would have reduced our cost. 

This is where it is really important that we need to ensure we write the absolutely necessary Unit Tests. This is also applicable if you practice TDD. You just don’t need to write Unit Tests for every method you write with in your application. Lets see some of these characteristics, and then how you decide what Unit Tests to write. 

If you are aiming to write Unit Tests for every method to make your manager happy with higher code coverage, then it is fantastic to write these types of tests. But did you know that most of your tests did not add much value to the quality of your system at all. You see your entire tests pass with green ticks. There are so many green ticks make you feel good. Someone could argue that “All the tests are there to ensure that every method behave as expected when it runs”.  Well not necessarily correct. Did you consider if you have to make a change to a component how much re-factoring need to be carried out? 

Let’s explain this with an example. When you have an obvious method, which takes a String parameter and returns a Boolean, and there are 100 methods calling this simple method, change to this method to return a String would require changing all those 100 methods. How about the repetition? Your Unit Test probably written to ensure that calling method takes a String value and returns a Boolean. Isn’t this repeating the same thing? How about the DRY? The time you have spent to write this Unit Test, you should have spent for some important task such as analysing some business requirements. 

Consider the future maintenance cost for both production code and all these Unit Tests? The amount of time you need to write Unit Tests for every single method, the amount of time you have to spend to write tests for complicated methods, which add no obvious benefits to the design of the system. They do not add any value at all. 

You may also reluctant to make changes to your code because of the amount to Unit Tests and the fear of breaking them.

Decisions 

So how you decide what Unit Tests to write. In order to decide this, you need to understand the types of methods you would normally write within your application. 

1.       Simple methods – These methods are very obvious and simple. Just by having a look at code you can clearly see what it does.  The code it self explains the design of it.

        /// <summary>

        /// Gets the first name from fulllname.

        /// </summary>

        /// <param>The full name.</param>

        /// <returns>First Name</returns>

        public string GetFirstNameFromFulllname(string fullName)

        {

            if (string.IsNullOrEmpty(fullName))

            {

                return string.Empty;

            }

            return fullName.Substring(0, fullName.IndexOf(” “));

        }

If you perform additional design and verification through Unit Testing, this method will give you a minimal benefit.

So if the method is simple and the design is obvious, you don’t need a Unit Test. If you are a TDD partitioner, the concept is the same. You do not need to write tests for every method you write within your application. 

2.       Components that are already tested – I see some developers trying test components that have already been tested by the framework.            

        /// <summary>

        /// Adds the companies to cache.

        /// </summary>

        /// <param>The company list.</param>

        public void AddCompaniesToCache(IList<Company> companyList)

        {

            if (companyList != null && companyList.Count() > 0)

            {

HttpContext.Cache.Add(“companyCahchkey”, companyList, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 15, 0), CacheItemPriority.Normal, null);

            }

        } 

The real purpose of this method is to add a list of companies to cache. A test would be to ensure the list is added to the cache. Why would do you need to write Unit Tests against this method when the ASP.NET caching – Cache  is already tested for its capabilities. You can also see this method is very simple and hence Unit Tests are not required. 

3.       Complex methods and have no value to the design at all

For example you may have a method that writes to a registry using a complex pattern, and then using a complex algorithm to generate some custom strings, then serializes the data before calling a web service.

It will be very exhaustive exercise to write dependencies for some of these complex methods. There are so many things and variations to consider. These methods are not related to your main design or requirements but to assist or help other methods to get the job done.  Most of these methods are self-contained algorithms. 

4.        High Level methods – There are methods within your application that integrated or calls other Units of methods. 

public void ManageResourceData(string resources)

        {

            if (string.IsNullOrEmpty(resources))

                throw new ArgumentNullException(“resources”);

            string retResourceValues = MergeResources(resources);

            SaveResourcesToAFile(resources);

            EmailReaources(resources);

            AddResourcesToDatabase(resources);

            SetUserPermission();

        } 

As you see here there are few units of methods being called. Writing Unit Tests for these types of methods, often waist of time. 

5.       Complex methods with so many dependencies.

Some refer to this as GOD methods. Most TDD practitioners not experience these type of methods as they would to like to perform one assert per single method. Also methods are smaller and always written for a single responsibility. You might come across with a situation where complex method with so many dependencies. The method itself performs so many other things and need to be re-factored in order to make it more testable. You can see these methods really hard to Unit Tests. You have two options

 a.       Re-factor your method and consider using interfaces, so you can mock all your dependencies during Unit Test.

b.       Simply do not waist your time to write the Unit Test. You may not have enough time to re-factor, and you can spend this time for something more useful.

Unit Tests

So the next important question is “What types of methods that you write Unit Tests against?”. The answer is not simple, which why you need to think carefully, before you write Unit Tests.

 If you an application author, you would consider writing Unit Tests against the method that actually define your requirements. The focus should be to write methods with less number of dependencies by providing a single responsibility, while focusing on a specific requirement. Your dependencies should be easily mockable. The same consideration is applied if you are practicing TDD. When you implement your method with, then to pass your Unit Test, you should consider it as defining a specific requirement. If not, the test it self does not add value to your app.

Requirements

The above graph displays the number of Unit Tests increases with the requirements. The more requirements you have the more Unit Tests you should have. 

For example you may have a high level requirement to write a Banking application where customer performs banking operations. When you design your application, you will consider more detail requirements, such as customers should be able to withdraw, deposit, transfer, print statements within your application. Regardless of wether you are TDD practitioner or not, you should consider writing Unit Tests for withdraw, deposit, transfer and print statements. By doing this you add the real quality to your application. You will have the confidence that your application performs as expected from the Unit Level.

You should not consider writing Unit Tests for any algorithms that may have to calculate your balances, encryptions, serializations, locked/isolated, or wether the database get initialised. These are some of the examples that you should avoid as they do not add much values your Unit Tests.

If you framework author you would consider writing Unit Tests ensure that the methods you have written confirms to the key design principles of your framework. Framework author should target the requirements, which provided by the design of the framework. For example, you are developing a resource management framework, and you need to ensure the developer who uses the framework could successfully retrieve images from your resource management system. So you would write a Unit Test to ensure that developers can retrieve images as expected.

I do not say that we should avoid Unit Tests and should not practice TDD. They both provide some real benefits to the application. However having unnecessary code / Uni Tests leads to more maintenance, and extra cost to projects. 

MVC2 Validation step by step

Out of the box, MVC 2 framework supports both server side and client side validation. 

Server Side validation is based on System.ComponentModel.DataAnnotations, and Client Side validation is based on ASP.NET Ajax 4.0.

Both Server and Client Side validation are loosely coupled, and they are joined using JSON

You can also have multiple validator providers plugged in and run at the same time. You can remove the built-in validation providers and you can create your own once. 

Prior to MVC 2, MVC 1 used third party frameworks and plug-ins such as xVal to enable both client side and server validation. MVC 2 allows you to enable both server side and client side validation without having to use any third party frameworks or plug-ins. 

This article explains how to enable both server side and client side validation step by step.

 Enabling server side validation.

Lets start with the View Model. Please refer to the DemoModel code sample below.

There is a DisplayName attribute for each property. This attribute produces the name, which you should display within the View. Form validation point of view, it doesn’t add any value at all. What is important here is the “Requiredattribute and “StringLengthattribute. These attributes belong to the System.ComponentModel.DataAnnotations namespace.

 There four built-in attributes that you can for validation. They are

  • Required
  • StringLength
  • Range
  • RegularExpression.

If any of above attributes doesn’t fit for your requirements, then you can easily create your own validation attribute if needed. For more info please refer to

http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx

 public class DemoModel

    {

        [Required]

        [DisplayName(“Product Code”)]

        public string ProductCode { get; set; }

        [StringLength(10)]       

        [DisplayName(“Product Description”)]

        public string ProductDescription { get; set; }

        [Required]       

        [DisplayName(“Product Date”)]

        public string ProductDate { get; set; }

    }

1.       This is how the View looks like.

(Please not that greyed code samples are not relevant to MVC validation.) 

<%@ Page Title=”” MasterPageFile=”~/Views/Shared/Site.Master” Inherits=”System.Web.Mvc.ViewPage<ValidationDemo.Models.DemoModel>” %> 

<% using (Html.BeginForm()) { %>

        <div>

            <fieldset>

                <legend>Product Information</legend>

                <div>

                    <%= Html.LabelFor(m => m.ProductCode)%>

                </div>

                <div>

                    <%= Html.TextBoxFor(m => m.ProductCode) %>

                    <%= Html.ValidationMessageFor(m => m.ProductCode) %>

                </div>               

                <div>

                    <%= Html.LabelFor(m => m.ProductDescription) %>

                </div>

                <div>

                    <%= Html.TextBoxFor(m => m.ProductDescription) %>

                    <%= Html.ValidationMessageFor(m => m.ProductDescription) %>

                </div>

                <p>

                    <input type=”submit” value=”Submit” />

                </p>

            </fieldset>

        </div>

    <% } %>

 You can see that I’m deriving from ValidationDemo.Models.DemoModel. So my View will be strongly typed and I can bind to the Model properties using m => m.ProductCode etc.

The value that enter to the ProductCode text box is bound to the value of the Model using <%= Html.TextBoxFor(m => m.ProductCode) %>

 The validation message is displayed using the html helper extension.

<%= Html.ValidationMessageFor(m => m.ProductCode) %> 

If you remove this line, your validation will still work, however no messages will be displayed. 

Importantly you must ensure that your form which require validation is placed in between <% using (Html.BeginForm()) {  } tags. (See above)

2.       One last thing to remember is that you need an action method within your Controller to be able to execute your form POST. You must also pass the model to your action method, as a parameter. 

    public class ValidationController : Controller

    {

        public ActionResult Demo()

        {

            return View();

        }

        [HttpPost]

        public ActionResult Demo(DemoModel model)

        {

            return View();

        }    

    }

3.       Now when you click on Submit button, server side validation will trigger and the error messages are displayed.

a

4.    Using ValidationSummaryControl

       If you need the validation summary control (most of you do), you have to add the following helper extension method to the View. You can add this helper method anywhere you like (within the View). 

       <%= Html.ValidationSummary(false, “Product creation was unsuccessful. Please correct the errors and try again.”) %>   

 The first argument (excludePropertyErrors: true/false) specifies whether you want display list of error underneath the ValidationSummaryControl.

b

Enabling client side validation. 

MVC 2, uses Microsoft AJAX 4.0 as the default client side library. You can also use the JQuery version of the validation library. It is in MVC 2 Futures project. You can download it from MVC2 Future library.

1.       Ensure you reference three JS files within your application.

 

If you are using MS Ajax:

<script src=”/Scripts/MicrosoftAjax.js”></script>

<script src=”/Scripts/MicrosoftMvcAjax.js”></script>

<script src=”/Scripts/MicrosoftMvcValidation.js”></script>  

If you are using Jquery

<script src=”/Scripts/jquery-1.3.2.min.js”></script>

<script src=”/Scripts/jquery.validate.min.js”></script>

<script src=”/Scripts/MicrosoftMvcJQueryValidation.js”></script> 

Within your View, before the <% using (Html.BeginForm()) { %> statement, you need to add the code: <% Html.EnableClientValidation(); %> 

  1. That’s it. Now run the app. You can see the client side validation in action.

c

If it is still not working, ensure the browser does not disable your JavaScript by default. For example in FireFox you need to ensure both Java and Javascript is not disabled. To be honest I don’t know why Java needed to be disabled. Please let me know if anyone finds out.

 Tweaks

Enabling Validation Summary Control for client side. 

Out of the box Validation Summary Control does not work for client side validation. For example you cannot display validation summary error massagers, within the Validation Summary Control during client side user interactions. To enable this you can implement a solution, which is described in the post here.