The Rain and The Shade

November 8, 2011

Have no logic in ye unit tests

Filed under: Unit Testing — ovaisakhter @ 3:26 pm

Recently I attended a seminar by Roy Osherove about good practices in unit tests.

Roy stressed hard that there should be no logic in the unit tests, I totally agree with that. He goes and on an explains that the logic in the unit tests can be symptom of two things

Missing Logic in your domain Model

If you have to write a lot of logic for a unit tests then it means that some one in their web application(or some other client application) will be writing the same logic.

This essentially means that if this logic changes at one place it will be have to be changed on the other places also, which will seriously hurt the maintainability of the unit tests. I like to consider as another client to your domain logic layer, more logic you have in business logic layers, less you will need to replicate in different clients.

A test that should have been divided into two or more tests

This is simple cohesion principal a test(or a method) should do only do one thing and do it well.

Who is testing my tests

There was an interesting question by Roy caught my attention “who is testing your tests?”. Your tests should not have logic as there is not one testing your unit tests.

I would like to believe that in most of the cases the unit tests and the code are in equilibrium state. So if one end is faulty the whole balance will be compromised. Unit tests check your code and the code checks your unit tests. In most of the situations when there is a bug in my unit test it will be fail as now it will not be doing what is expected of it. So I do not fully agree with this reason none the less I totally agree with the concept itself.

Advertisements

September 4, 2011

What to inject and what not to inject is the question..

Filed under: Unit Testing — ovaisakhter @ 6:51 pm

Some days back I was having a chat with a friend of mine regarding unit test and DI, we were going though his code and we started discussion on some of the service locators in his services code which I thought should also have been injected(DI or IoC), but he disagreed as he thought these locators are generic enough so they do not need to be injected or wrapped or abstracted. In the similar lines one my team members created a static configuration class in the core and was using it to access the configuration for the application, which started the discussion on how far your should go when it comes to dependency injection.

To answer this question I tried to look into an extreme example in my code and how it paid off in the end.

Recently in a project I wrote some services which were saving certain statistics about a website. An Asp.Net MVC application was calling my application controller service to store the  statistics. These statistics are saved in the context of a Date. In this scenario I can easily use a DateTime.UtcNow.Date inside my service for the Date and be done with it. The challenge comes when you have to write unit tests for this situation. We need to generate some sample data to test the system properly. Considering this situation I created an interface to inject the Date.

public interface IClock
    {
        DateTime Get();
    }

In my unit test project I created an implementation of this such that I can set the Date externally.

Now I created a method in my unit test project

internal class DateProvider : IClock
    {
        public DateTime CurrentDate;

        public DateProvider()
        {
        }

        public DateTime Get()
        {
            return CurrentDate;
        }
    }

I wrote a some code to generate random statistics and recorded the data created in the memory so that I can test it later on. Here is how the code looks like

           var daysToGoBack = random.Next(400, 1000);

           var dateTimeProvider = new DateProvider();
           var externallyControlledActionNotifier = new ExternallyControlledActionNotifier();
           var memorybasedStatisticsLogger = new MemorybasedStatisticsLogger(new IPBasedServerIdentityProvider(),
                                                                             new SiteStatisticsRepository(),
                                                                             externallyControlledActionNotifier, dateTimeProvider);

           for (var i = 0; i < 1000; i++)
           {
               dateTimeProvider.CurrentDate = DateTime.UtcNow.Date.Subtract(TimeSpan.FromDays(random.Next(0, daysToGoBack)));

               memorybasedStatisticsLogger.LogSiteView(surveyConfiguration.RowKey);
               testStatistics.Add(new Statistics { Day = dateTimeProvider.CurrentDate, PageViewed = true })
;

 

so now I am able to generate a random date in the past and I am able  to record in memory the data created so that I can test that correct data was created by my services or not.

As you can see that in this situation injecting a trivial thing like date has saved the day in terms of unit testing. So I believe that you should to inject every possible dependency as a convention, it may come handy at some time….

August 17, 2011

Unit Testing Database driven functionality with ADO.Net Entity Framework Code First

Filed under: ADO.Net Entity Framework,Unit Testing — ovaisakhter @ 5:39 am

The basic principal of writing a unit tests is that when you do a transaction you know the “expected” result and then you compare with the actual result that was generated, and if these results match you have a passed unit test. 

It is always interesting to write unit tests for Database services. Usually the problem that comes to mind is how to exactly predict the state of the database at the time when unit tests are running, so that the unit tests know what to expect. Some people may argue that you can mock out all the database functionality (mock the repositories), this idea may be very applicable in some scenarios but I usually do not go this way because of two reasons, 

  • It seems like to much work
  • Our applications are mostly data driven applications so there is not much to test anyway other than database transactions.

One way of knowing the exact state of the database can be to initialize(create) the database every time the unit tests are run. Once the database is created we might want to insert some initial data which is required for the unit tests.

I have been using Entity Framework Code first in my recent projects. Entity Framework provides you a very good way of achieving the two objectives I have mentioned in the previous paragraph.

EF provides a concept of Database initializers, these are implementations which define the strategy of how (rather when) the database will be created using our model (if you are a bit lost then I recommend to watch Code First Development with Entity Framework). These implementations implement an Interface called IDatabaseInitializer. There are some pre-backed strategies for database creation are provided with the EF. The one we are interested here is DropCreateDatabaseAlways. The name says it all, when using this strategy a database will be created every time code is executed(unit tests are run). To use the Initializers all you need to do is to write the following code before your unit tests are executed

System.Data.Entity.Database.SetInitializer<MyDbContext>(new DropCreateDatabaseAlways<MyDbContext>());

(Make sure you are using a local database server(SQL Express), things can really stressed if you are using a shared development server Smile.)

So now our database is created every time unit tests are run, now we need to create some data each time the database is created. For this you can inherit the  DropCreateDatabaseAlways class and override a method called Seed. using this method you add the initial records you want to create every time database is created.

Here is how the code will look like

public class MyUnitTestDatabaseInitializer : DropCreateDatabaseAlways<MyDbContext>
   {
       protected override void Seed(WilkeDbContext context)
       {
  //you can add any data using the context objected provided in the parameter

           context.SaveChanges();
           base.Seed(context);
       }
   }
The seed method is called just after the database is created by the the framework. Now all you need to do it to tell the framework to use your Database Initializer, and that you will do by modifying the code I wrote above.

System.Data.Entity.Database.SetInitializer<MyDbContext>(new MyUnitTestDatabaseInitializer <MyDbContext>());

so here you have it, now you can write the unit tests which are totally predictable and can run on any environment, be it your local machine or your Build Server. 

August 3, 2011

Something beautiful while using AutoFixture

Filed under: Unit Testing — ovaisakhter @ 5:39 pm

In one of the projects I have the following class

public class SiteSurveyConfiguration : Entity
    {       
        public string CustomerName { get; set; }

        public string Website { get; set; }

        public string ShortDescriptionOnPopup { get; set; }

        public string HeadlineOnPopup { get; set; }

        public string LabelOfButtonOnPopup { get; set; }

        public int PercentOfUserWhoWillSeePopup { get; set; }

        public string CustomerLogoImageUrl { get; set; }

        public int ClicksByUserBeforePopShown { get; set; }

        public string ColorOfHeadline { get; set; }

        public string ColorOfShortText { get; set; }

        public string ColorOfButton { get; set; }

        public string FontOfPopup { get; set; }

        public int WidthOfPopup { get; set; }

        public int HeightOfPopup { get; set; }

        public bool ShowPopupInIFrame { get; set; }       
    }

While unit testing I needed to create a list containing 10 instances of this class along with different random data in each field.

var ListOfConfigurations = new List<SiteSurveyConfiguration>();
          var fixture = new Fixture();
          fixture.AddManyTo(ListOfConfigurations,10);

So this code created 10 instances of my class, added data to each field and added these instances to my list. I almost had tears of joy in my eyes Smile.

you can get more information about AutoFixture from http://autofixture.codeplex.com/

 

 

Create a free website or blog at WordPress.com.