Sunday, January 27, 2008

To Blog or not to Blog

There's some good writing out there whether one should start blogging or not. Actually, there is no excuse for a developer why they shouldn't. If a Mort like me does it (and I'm still doing a terrible job), why shouldn't you?

Friday, January 25, 2008

Code Coverage with TeamCity

In my previous post on JetBrains TeamCity I mentioned that it has no support for .NET code coverage.  With this post I want to correct the injustice of this statement. It was a simple case of RTFM that solved this issue. Actually this great post pushed me into the right direction (you can even download some specific TeamCity MsBuild tasks).

One might think you have to jump through quite some hoops in order to integrate code coverage, but it is actually really easy. Here goes:

1. Make sure that your build script creates a code coverage report. I'm using NCover/NCoverExplorer for this with the corresponding MsBuild tasks that you can download here (in the NCoverExplorer Extras package).

2. Add the code coverage results file to the artifacts:TeamCityArtifacts

3. Add the following line to the TeamCity Data Directory/config/ main-config.xml file as described here:

<report-tab title="CodeCoverage" basePath="" startPage="CodeCoverage.html"/>

4. You're done.

Now behold the results:

TeamCityCodeCoverage

It creates a new tab for the build results that integrates the code coverage artifact. The coolness of TeamCity just keeps amazing me.

Wednesday, January 23, 2008

22 books

I've put a large part of what is on my bookshelf on 22 books. This web site is James Avery's experiment with Ruby on Rails. Give it a try. It looks very promising.

TeamCity Continuous Integration & Build Management is really awesome

I've been goofing around with TeamCity over the last week. After reading some posts about TeamCity (1)(2), I decided to give it a try. In my continuous quest to eliminate the amount of XML programming in my life, I decided to replace my current CruiseControl.NET setup for my home project with TeamCity.

I couldn't believe how easy it was. I installed the server and got my first project up-and-running in about 15 minutes. At first, I was in complete denial. I must have done something wrong here. Then it hit me. This is how its supposed to be. TeamCity is what TFS and CC.NET should be like when they grow up. Don't take my word for it, take a look for yourself:

TeamCity

Sweet statistics huh? Setting up a new build is really simple.

TeamCity2

Not everything is sunshine and happiness though. The shortcomings I encountered up till now are:

  • No out-of-the-box support for NUnit 2.4. I hope that the brilliant people at JetBrains put out an update soon.
  • No support for code coverage whatsoever (at least, I couldn't find it in the docs or on the web). Bummer.

Opposed to these shortcomings, there is a quite an impressive feature list for both Java and .NET:

TeamCity3

I still have to take a look at the Duplicates Finder as it looks great too.

Now here comes the good news. You can download the professional edition for free! You can create 20 build configurations and make use of three different build agents which should be more than enough for small teams.

After becoming a real Resharper addict (can't use Visual Studio without it), I'm now becoming a slave to TeamCity as well. I've converted all my home projects, and life has never been better. Till next time.

Sunday, January 13, 2008

AutoMocking Container

When writing unit tests that involve interaction based testing, you most likely end up using one of the mocking frameworks out there. The mocking framework I'm using is Rhino Mocks. For an explanation of the differences between state based testing and interaction based testing, you can have a look at the excellent Mocks aren't Stubs from Martin Fowler. For a nice introduction on Rhino Mocks, have a look at this screen cast.

Anyway, when writing interaction based unit tests for the following code

public class CustomerService { private ICustomerRepository _customerRepository; private IActiveDirectoryGateway _activeDirectory; public CustomerService( ICustomerRepository customerRepository, IActiveDirectoryGateway activeDirectory) { _customerRepository = customerRepository; _activeDirectoryGateway = activeDirectory; } public void CreateCustomer(Customer customer) { Boolean succeeded = _customerRepository.Save(customer); if(succeeded) { _activeDirectory.GrantAccessTo(customer); } } }

you probably end up writing unit tests like this:

[TestFixture] public class ClassicCustomerServiceTestFixture { private MockRepository _mockRepository; private ICustomerRepository _customerRepository; private IActiveDirectoryGateway _activeDirectoryGateway; private CustomerService _customerService; [SetUp] public void SetUp() { _mockRepository = new MockRepository(); _customerRepository = _mockRepository .DynamicMock<ICustomerRepository>(); _activeDirectoryGateway = _mockRepository .DynamicMock<IActiveDirectoryGateway>(); _customerService = new CustomerService(_customerRepository, _activeDirectoryGateway); } [TearDown] public void TearDown() { _customerService = null; _activeDirectoryGateway = null; _customerRepository = null; _mockRepository = null; } [Test] public void VerifyInteractionWithCustomerRepository() { Customer customer = new Customer(); using(_mockRepository.Record()) { Expect.Call(_customerRepository.Save(customer)) .Return(false) .Message("Expected Save to be called once."); } using(_mockRepository.Playback()) { _customerService.CreateCustomer(customer); } } [Test] public void VerifyInteractionWithActiveDirectoryGateway() { Customer customer = CreateCustomer(); using(_mockRepository.Record()) { SetupResult.For(_customerRepository.Save(null)) .IgnoreArguments() .Return(true); _activeDirectoryGateway.GrantAccessTo(customer); LastCall.Message("Expected GrantAccessTo to be called once."); } using(_mockRepository.Playback()) { _customerService.CreateCustomer(customer); } } private static Customer CreateCustomer() { return new Customer(); } }

As you can see, there is a lot of code in the SetUp method that creates mock objects for the dependencies that are required by the subject under test ( = the CustomerService class). Besides the fact that you need to type it over and over again for every test fixture, the major disadvantage with this approach is that the unit tests are not self-containing. Reading and understanding the unit tests involves reading both the test case methods and the SetUp/TearDown methods.

The approach I've been using for the last couple of months is the AutoMocking container from Jacob Lewallen. Lets speak code shall we.

[TestFixture] public class CustomerServiceTestFixture : AutoMockingTestFixture<CustomerService> { [Test] public void VerifyInteractionWithCustomerRepository() { Customer customer = new Customer(); using(MockRepository.Record()) { Expect.Call( MockCustomerRepository.Save(customer)) .Return(false) .Message("Expected Save to be called once."); } using(MockRepository.Playback()) { CreateSubject().CreateCustomer(customer); } } [Test] public void VerifyInteractionWithActiveDirectoryGateway() { Customer customer = CreateCustomer(); using(MockRepository.Record()) { SetupResult.For( MockCustomerRepository.Save(null)) .IgnoreArguments() .Return(true); MockActiveDirectoryGateway. GrantAccessTo(customer); LastCall.Message("Expected GrantAccessTo to be called once."); } using(MockRepository.Playback()) { CreateSubject().CreateCustomer(customer); } } private ICustomerRepository MockCustomerRepository { get { return Mock<ICustomerRepository>(); } } private IActiveDirectoryGateway MockActiveDirectoryGateway { get { return Mock<IActiveDirectoryGateway>(); } } private static Customer CreateCustomer() { return new Customer(); } }

Notice how the SetUp/TearDown methods are completely gone. I've created this base class test fixture, called AutoMockingTestFixture that encapsulates the use of the AutoMocking container, like so:

public abstract class AutoMockingTestFixture<TSubject> { private AutoMockingContainer _autoMockingContainer; protected AutoMockingContainer AutoMockingContainer { get { return _autoMockingContainer; } } protected MockRepository MockRepository { get { return _autoMockingContainer.MockRepository; } } protected T CreateSubject() { return _autoMockingContainer.Create<TSubject>(); } protected T Mock<T>() where T : class { return _autoMockingContainer.Get<T>(); } protected T Stub<T>() where T : class { _autoMockingContainer.Mark<T>().Stubbed(); return _autoMockingContainer.Get<T>(); } protected virtual void SetUp() {} protected virtual void TearDown() {} [SetUp] public void BaseSetUp() { _autoMockingContainer = new AutoMockingContainer(new MockRepository()); _autoMockingContainer.Initialize(); SetUp(); CreateSubject(); } [TearDown] public void BaseTearDown() { TearDown(); _autoMockingContainer = null; } }

Using this base test fixture ensures that all interaction based unit tests in the derived test fixture are completely self-containing. Everything you need to know about a particular unit test is right there in the same method. Another big advantage is the fact that you can now add dependencies to the constructor of the CustomerService class without breaking any tests whatsoever.

If you're interested in using this approach, the code for the AutoMocking container can be downloaded from Ayende's Subversion repository (see rhino-testing). Under the hood, the AutoMocking container leverages Castle Windsor for doing its magic.

Thursday, January 10, 2008

FeedDemon

My favorite RSS reader is now free of charge.

FeedDemon

Get it while its hot!

Tuesday, January 08, 2008

Total Commander Rocks!

I'm a huge fan of Total Commander for as long as I can remember. Thinking about it, I'm using it for more than 10 years now. Today, I accidentally discovered a very nice feature:

TotalCommander

It seems that using the shortcut CTRL-T works the same like in a web browser. To say it with the famous words of a colleague of mine:

This blows my mind.

Man, I love using this tool!

Monday, January 07, 2008