While working on Tiler I experimented with the new options in Visual Studio 2012 for doing Test Driven Development. I have to say I’m pleasantly surprised.
So let’s take a look at the what, why and how of TDD and some new stuff from Microsoft Research.
What is TDD
Test Driven Development is a way of developing your software guided by unit tests.
When you are in the TDD flow, you first write a unit test that defines the functionality you want to create. This test will obviously fail because you don’t have the functionality in place yet. Then you start fixing your test by implementing the functionality that is necessary to make your test succeed. After that you improve the quality of your code by refactoring.
This keeps you on track while developing your code and it will make sure that you are not ‘over developing’. You only write the code that is absolutely necessary to make your test succeed.
After fixing your failing unit test, you take a look at your code and refactor where necessary. You can do this safely because you are certain that your unit test provides a safety net if you introduce a bug.
TDD also helps wit the design of your code. Because you are in the mindset of thinking about which functionality you want, you design your class interface to expose this nicely. Instead of focusing on the inner workings of your class and crafting the perfect algorithm or something, you focus on what your ‘client’ needs.
As we looked at in the article Unit Testing, hell or heaven?, writing good testable code can be a challenge. With TDD, you force yourself to write code that is testable. Checking your code coverage (the amount of code that is executed and checked by your test) you can make sure you are not writing code without a test.
Why TDD
Some people asked me why I would use TDD on a one man project. Personally, I don’t see any reason why not to use it!
The benefits of TDD also apply when doing a solo project.
For example, developing the game rules for Tiler is something that lends itself nicely to a TDD process. I’ve created a set of unit tests that mimic certain game positions to check if a move is valid or not. Also for more general things like inviting other players or registering for an account TDD is helping me with sketching out the functionality and speeding up my development
How to TDD in 2012
Visual Studio 2012 has some nice improvements to make Test Driven Development easier.
There is a new Test Explorer that replaces the Test Results View in Visual Studio 2010.
The new test explorer offers a nice list of all your unit tests and helps you in quickly seeing which tests are failing.
It especially helps with the whole Red-Green-Refactor process. It supports running your unit tests after each build and it will run failed tests first so you get feedback on the most important items.
This is how the test explorer looks like in VS 2012:
The Test Explorer currently only shows your Unit Tests. Other tests (like Coded UI tests) are not shown in the Test Explorer. This is to make sure that all the test shown can run fast and can be executed after each build. The Test Explorer was developed with an eye on extensibility. If you go to Tools —> Extensions you can select other testing frameworks like XUnit or QUnit. They will automatically integrate with your Test Explorer so you don’t need to customize or configure anything if you don’t want to use MSTest.
Notice the button in the toolbar that lets you activate the ‘Run Tests After Build’ option
Automatically run tests after build
If you activate it and execute a build, Visual Studio will run all your unit test and clearly signal it when something went wrong:
This definitely helps you getting in the TDD flow of ‘Red-Green-Refactor’!
The refactor tooling is still the same as in Visual Studio 2010 as far as I can see but maybe with Roslyn we can see some nice improvements in that area.
The Test Explorer also supports executing code coverage for your unit tests (or for a single unit test). Other frameworks like XUnit integrate nicely with this and have the same options as MSTest.
Testing the untestable
Another improvement that came out of Microsoft Research is the new Microsoft Fakes Framework. The Fakes framework helps with creating and injecting testable code into a system under test. This should help with testing code that has hard dependencies (which is a bad thing!)
Personally, I have to say that the Fakes framework is a really nice piece of code. But it tries to fix the symptoms, not the cause of unit testing problems. Writing code that is testable from the beginning is a better solution then using something like the Fakes framework.We already have some pretty good mocking frameworks like RhinoMocks that offer a Arrange, Act, Assert process. I’m afraid that the new Fakes framework will lure new TDD developers into the false assumption that hard coded dependencies are a good thing and the Fakes framework is the way to go.
But ok, before completely dismissing the framework, let’s take a look at it. It has two important pieces:
- Stubs, used to test code that uses interfaces or non-sealed classes. It will default to the default behavior of the type you are stubbing and it offers you the functionality to replace this default behavior with something more suitable for your test.
- Shims, used to test code that is otherwise untestable.Things like hard coded dependencies or the use of static functions can be changed.
Let’s take a look at how to use Shims. Take this code for example:
// system under test
public static class Y2KChecker
{
public static void Check()
{
if (DateTime.Now == new DateTime(2000, 1, 1))
throw new ApplicationException("y2kbug!");
}
}
How would you test this code? If you wanted to make sure that an exception is thrown on 1-1-2000, your test would only succeed on 1-1-2000. Since DateTime.Now is a hard coded dependency, we can’t alter it in our test.
However, when selecting an assembly reference in the solution explorer, we now have the option to generate a Fakes assembly. This will add some assemblies to your project so you can now do the following:
[TestMethod]
public void TestSomeDateTimeStuff()
{
using (ShimsContext.Create())
{
ShimDateTime.NowGet = () => new DateTime(2000, 1, 1);
Y2KChecker.Check();
}
}
You use the Shim type to override the behavior of DateTime.Now. This value will then be used in Y2KChecker.Check() and the exception will be thrown.
Time to get started
Visual Studio 2012 definitely has some nice improvements when using TDD and Unit testing in general. The new Test Explorer and the option to run your tests after each build really help getting in the flow.
Microsoft Fakes framework is another story. It will have its uses although I’m still a little skeptical and I would not advice it as ‘the way to go’ when writing testable code.
Visual Studio 2012 has a Go-Live license so you can download it right now and start using it to get into the flow while doing your own TDD!