Friday, June 22, 2012

How will another unit test framework cause me to write better tests than using MSTest ?

 I started out with an idea of writing down some of the things I discovered while writing unit tests on both MSTest and the popular NUnit unit testing frameworks and for the most part I wasn't impressed with MSTest. The article developed on how MSTest sucks (the one fore Visual Studio 2010) and how NUnit rules (ok its a bit biased and exaggerating but get this...) but I got hit with one fundamental question...

How will another unit test framework cause me to write better tests than using MSTest?

You see you can have all the "nice features" in the world but if you still write unit tests against a system that isn't well designed or broken up in testable pieces, you will have a hard time writing maintainable unit tests. The other thing is that even if you have the most wonderful designed system and unit-test friendly classes to test against, you still sit with the problem of writing maintainable unit tests.
So I thought of rewriting the post and taking on this discussion from a different perspective. Instead of blabbering on about how this framework rocks and the other one doesn't let's ask the question above. Why against MSTest? Because it seems to be the underdog at the moment. Look at what some of the other bloggers have to say:
I also have a couple of things to say about it which I just quickly want to add before I ask the big quesiton.
  • Firstly it seems to be another monolithic solution from Microsoft. Why not have a .NET testing solution which can be broken down in different testing modules so that you can use the best tool for the job? So then you can use the other testing tools from Microsoft but for Developer unit testing you use something like NUnit or something. But I know why this is the case because again Microsoft wants you to use their products. Now it wouldn't have been a problem if they have taken certain things into account like some of the bloggers up there have stated like extensibility, etc.
  • Startup time is SLOW! And then it's only basic logic tests!
  • There are plugins in Visual Studio to run NUnit tests that are free! (Not a MSTest gripe but many people stick to MSTest because its integrated. Speaking of which there are ways apparently, which I haven't tested myself, to run NUnit on a TFS build server. Check this link: "NUnit for Team Build").
So now I want to start this question objectively and look at how using the best features of unit tests allow me to write more maintainable unit tests. But in instead of taking every unit testing framework I will settle with NUnit and MSTest because I am familiar with NUnit and it seems to be the most popular one out there, and MSTest because everyone is slashing this one to bits so it should provide a nice view if they really make a difference.
Now you might say "I've done this and that with MSTest and it took me hours while I could have done the same in NUnit in minutes". Let's find out shall we?

I'm not going into UI tests and Web tests. Firstly I don't think something like NUnit should be brought anywhere near UI testing! MSTest might have a nice UI tester but you might need to purchase Visual Studio Ultimate or something to get hold of it. Neither am I going to do web tests which involve HTML and JavaScript! That's just a maintenance nightmare waiting to happen!
No I will solely stick to logic tests and maybe even integration tests. Let Developer unit testing BE developer unit testing, anything else, use some of the other tools that are more suited for the job!

Writing tests for small methods are fine because your tests are inherently small to test the small amount of work it needs to do. Stuff like math functions, you give it an input and it spits out an output, very simple and quick. You do the MATH! LOL!
Some of you may say "Well NUnit will simplify your life there, you can have 1 test method with a few value attributes". That's true so NUnit can give you some simplified and good test coverage there. MSTest will require the code duplicate approach or you have to write the plumbing (again it might not be what developers would like as MSTest is not as extensible as NUnit) to get to the same kind of ease-of-effort that NUnit guys are enjoying.

But let's make it more interresting!

How about writing tests against a WCF service where you need to stub out some calls to other services and have to validate that the correct logic is being followed?

So let's say I have a WCF service class:

public class TimeSheetService : ITimeSheetServiceContract
{
       public PersonDetails GetPersonDetails(string id)
       {
            ... some code here ...
       }
}

Ok seems easy to test:

NUnit

[Test]
public void Get_user_details_from_timesheetservice_that_is_existing()
{
     TimeSheetService service = new TimeSheetService();
     var person = service.GetPersonDetails("12345");
     Assert.That(person, Is.Not.Null);
     Assert.That(person.Name, Is.EqualTo("James"));
}

MSTest

[TestMethod]
public void Get_user_details_from_timesheetservice_that_is_existing()
{
     TimeSheetService service = new TimeSheetService();
     var person = service.GetPersonDetails("12345");
     Assert.IsNotNull(person);
     Assert.AreEqual("James", person.Name);  
}

Not much of a difference, right? But hang on a moment! Where do I stub the person with the name "James"?
Big deal, I'll just use my favorite mocking framework to do that.
I currently use Rhino Mocks as my mocking framework and I am open for discussion, so if you see me doing something wrong or you want to notify me on something else that Rhino Mocks users will like to move across to please let me know. Assume I have a preconfigured 'mock' object (will get to that later) and I have noticed that the service needs an IPersonRepository object.

NUnit

[Test]
public void Get_user_details_from_timesheetservice_that_is_existing()
{
     IPersonRepository personRepository = mock.StrictMock<IPersonRepository>();
     personRepository.Expect(x => x.GetPersonDetailsFromRepository("12345")).Return("James");
     mock.ReplayAll();

     TimeSheetService service = new TimeSheetService(personRepository);
     var person = service.GetPersonDetails("12345");
     Assert.That(person, Is.Not.Null);
     Assert.That(person.Name, Is.EqualTo("James"));

}

MSTest


[TestMethod]
public void Get_user_details_from_timesheetservice_that_is_existing()
{
     IPersonRepository personRepository = mock.StrictMock<IPersonRepository>();
     personRepository.Expect(x => x.GetPersonDetailsFromRepository("12345")).Return("James");
     mock.ReplayAll();

     TimeSheetService service = new TimeSheetService(personRepository);
     var person = service.GetPersonDetails("12345");
     Assert.IsNotNull(person);
     Assert.AreEqual("James", person.Name);  
}

See how much it grew? Both are still the same length. The problem is that this is how we generally run into these things. If we don't take care, we usually end up with bloated unit test methods!
Now's the question is how can the unit testing framework make my life simpler?
Now let's forget using other libraries (AutoFixture as example) and let's forget writing helper methods (unless it's part of getting the framework to help deal with this). Let's get the unit testing framework to do most of the work for us. See what I mean with this? I know that there are stuff out there that can help deal with this but that's not the point. Can my unit testing framework help take care of this without me having to write helper methods/classes or rely on external solutions? If it cannot, then why? Those are the things I want to point out.

And so I present this as a question to you the reader. I know MSTest and I know NUnit but I don't know all the integral details that each offer to leverage it to my advantage. So if you look at the above and see some area where MSTest or NUnit can make my life easier please comment below. If you are experienced in another unit testing framework, please give your input as well! You don't necessarily have to give big code replies, just mentioning a feature and how it can be applied should help get a picture.

Just to finalize this let me give a broader picture of the problem and then hopefully people can start sharing their input so that we can really see how much of a difference a unit testing framework makes.

First there is the Rhino Mocks problem. How can I create a new MockRepository for each test and provide it in such a way that when I call the field (or property) "mock" that I have a ready to be used mock. Also don't forget that Rhino Mocks expect the "ReplayAll" to be called before you call your SUT (System Under Test) code and after the test is completed it need to "VerifyAll" against the mock repository object.

Secondly I want to test something else. I want to test the SubmitTime method.
Let me write out the code (only the relevant stuff) so that you can have a clearer picture of what needs to be tested:

public class TimeSheetService : ITimeSheetServiceContract
{
      private readonly IPersonRepository _person;
      private readonly ITimeCaptureRepository _timeCapture;

      public  TimeSheetService(IPersonRepository person, ITimeCaptureRepository timeCapture)
      {
             _person = person;
             _timeCapture = timeCapture;
      }

      public PersonDetails GetPersonDetails(string id)
      {
              var result = _person.GetPersonDetailsFromRepository(id);
              return new PersonDetails { Name = result.Name, Categories = result.Categories };
      }

      public bool SubmitTime(TimeSubmitRequest request)
      {
             PersonDetails personDetails = GetPersonDetails(request.PersonId);
             bool added = _timeCapture.SubmitTimeCapture(request.PersonId, personDetails.Categories, request.TimeSlots);
             return added;

      }
}

Now the Id or PersonId is a string, Categories are IList<string> and TimeSlots are IList<TimeSlot> and TimeSlot is of class of properties { DateTime StartTime, int Minutes, string Category }

If there are somethings that are not clear let me know.

    Wednesday, November 09, 2011

    Renewal Project's WCF Extensions Library

    Hi all

    Just wanted to announce that I've released a beta-version of my WCF Extensions Library on my CodePlex project called Renewal Projects. Check out the documentation section for more info. I think WCF users in the .NET space may want to have a look at this as it might prove useful in the long run as it contains a Channel Repository, Channel Pool and the possibility to have WCF channels hosted in a IOC container.
    Its in BETA at the moment but testers are welcome to try it out.

    http://renewalprojects.codeplex.com/

    Wednesday, November 02, 2011

    MVC 2 Hidden Helper Extension

    I don't know if you've ever needed to store an entire entity object inside a html page using the hidden form fields but for some reason the standard ASP.NET MVC HiddenFor() method doesn't do that. It only seems to work for simple data types such as ints and strings, etc.
    So I wrote a little helper method to do just that.
    It takes all the entity that you wish to store in your HTML page and iterates over each property and performs a Hidden() method call on them to ensure that all its properties are encoded as hidden fields so that it gets passed back to the Controller Action via the POST method.

    public static MvcHtmlString HiddenEntirelyFor<TModel, TResult> (this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TResult>> expression)
    {
       ModelMetadata modelMetadata =
          ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
       List<string> htmlEntries =
          modelMetadata.Properties
             .Select(property => htmlHelper.Hidden(ExpressionHelper.GetExpressionText(expression) + "." + property.PropertyName, property.Model, null))
             .Select(mvcHtmlString => mvcHtmlString.ToHtmlString())
             .ToList();
       return MvcHtmlString.Create(String.Join(Environment.NewLine, htmlEntries.ToArray()));
    }

    Monday, September 05, 2011

    Moles with Mocking capability

    Myself and a colleague of mine made a discovery when we started to do some unit test coding with moles that it doesn't have any expectation-functionality like Rhino mocks where you can specify what the incoming parameter values should be for a mocked-class.

    That's when I did some searching on the web for mocking frameworks which might complement the Moles tool-set. I came across this library: http://simpledotnet.codeplex.com

    It's not the best out there but it does feature one thing that other mocking frameworks (and correct me if I'm wrong) doesn't have and that is delegate mocking. I told my colleague about it and he tried it out... and it worked! It makes coding less and improves readability.

    Now suppose you have a class ClassX that you want to mock.
    Now with Moles you can only stub the target type by substituting the behavior with delegates.
    With Simple.Net, you first create the expectation scope:

    var expectationScope = new ExpectationScope();

    Then you can create the mock-delegate:

    var getNameMock = Mock.Delegate<MolesDelegates.Func<ClassX, string>>();

    Now we stub the target class with the mock:

    MClassX.AllInstances.GetName = getNameMock;

    Now you set some expectations:

    Expect.Exaclty(1).MethodCall(() => getNameMock(Any<ClassX>.Value)).Returns("Fred");

    Run your system under test code:

    ClassX x = new ClassX();
    Assert.AreEqual("Fred",x.GetName());


    Verify expectations are met:

    AssertExpectations.IsMetFor(expectationScope); 

    And now your test should succeed. Please check out the Simple.NET website to see how this mocking framework works.

    Hope this helped someone.