Getting started unit testing is a difficult task. I've seen plenty of people learning to unit test and it took some time for me and seems to take some time for everyone before unit testing really clicks. Part of the reason why unit testing is difficult for people to get started with is that the code most developers write is not testable. Yes, not only is it important to test, but it is important for your code to be testable. Most code is so difficult to test that anyone who doesn't know how to unit test will have a great deal of trouble testing anything.
Most testing is difficult because the code you're trying to test has too many dependencies. So we all know that we write code which depends on other code we write. There are a few important dependencies that a lot of people forget about.
Breaking the DateTime Dependency
One seemingly safe piece of code to test is the DateTime class. How is it often used? Well, people use DateTime.Now or DateTime.Today in their code. So what is the big deal? Isn't this easy to test? NO! Testing a method which uses either of those two values is not easy at all. If your application cares about the time of day at all, it is impossible to test it reliably if you're using DateTime.Now.
Two cases for time come into my mind right now: checking for weekends and checking morning, afternoon, and evening. A couple of interesting sites I enjoy change the theme of the site based on the time of day. How could you test that logic? Well, not easily if you're using DateTime directly. To get around this wee need to break the dependency. To do this we need to work with an interface which gives us access to all the logic we used from the DateTime class.
interface ICalendar
{
DateTime GetCurrentTime();
DateTime GetCurrentDate();
}
public class Calendar : ICalendar
{
#region ICalendar Members
public DateTime GetCurrentTime()
{
return DateTime.Now;
}
public DateTime GetCurrentDate()
{
return DateTime.Today;
}
#endregion
}
If you need any more attributes from the DateTime class add the methods for them to the interface and the class.
In order to use these methods in production with our TimeOfDay class, we will need to do a couple of things. As a general rule, it is important to program against an interface. We will start by creating a stub for the class and then testing the stub.
public class TimeOfDay
{
private ICalendar _calendar;
public TimeOfDay() : this(new Calendar())
{
}
public TimeOfDay(ICalendar calendar)
{
_calendar = calendar;
}
public bool IsMorning()
{
throw new NotImplementedException();
}
public bool IsEvening()
{
throw new NotImplementedException();
}
}
Now we go and write a couple of test methods which we want to have fail since we haven't implemented our methods yet. Then once we've got the tests in place we can fill in the code and have confirmation that we have written it correctly.
[TestClass]
public class TimeOfDayTester
{
private FakeCalendar _myFakeCalendar;
public TimeOfDayTester()
{
_myFakeCalendar = new FakeCalendar();
}
[TestMethod]
public void OneMinuteBeforeTenAMShouldBeTheMorning()
{
_myFakeCalendar.CurrentTime = new DateTime(2001, 1, 1, 9, 59, 00);
TimeOfDay timeOfDay = new TimeOfDay(_myFakeCalendar);
Assert.IsTrue(timeOfDay.IsMorning());
}
[TestMethod]
public void NoonShouldNotBeTheMorning()
{
_myFakeCalendar.CurrentTime = new DateTime(2001, 1, 1, 12, 00, 00);
TimeOfDay timeOfDay = new TimeOfDay(_myFakeCalendar);
Assert.IsFalse(timeOfDay.IsMorning());
}
[TestMethod]
public void EightPMShouldNotBeTheMorning()
{
_myFakeCalendar.CurrentTime = new DateTime(2001, 1, 1, 20, 00, 00);
TimeOfDay timeOfDay = new TimeOfDay(_myFakeCalendar);
Assert.IsFalse(timeOfDay.IsMorning());
}
[TestMethod]
public void SixPMShouldBeTheEvening()
{
_myFakeCalendar.CurrentTime = new DateTime(2001, 1, 1, 18, 00, 00);
TimeOfDay timeOfDay = new TimeOfDay(_myFakeCalendar);
Assert.IsTrue(timeOfDay.IsEvening());
}
[TestMethod]
public void NoonShouldNotBeTheEvening()
{
_myFakeCalendar.CurrentTime = new DateTime(2001, 1, 1, 12, 00, 00);
TimeOfDay timeOfDay = new TimeOfDay(_myFakeCalendar);
Assert.IsFalse(timeOfDay.IsEvening());
}
[TestMethod]
public void EightAMShouldNotBeTheEvening()
{
_myFakeCalendar.CurrentTime = new DateTime(2001, 1, 1, 8, 00, 00);
TimeOfDay timeOfDay = new TimeOfDay(_myFakeCalendar);
Assert.IsFalse(timeOfDay.IsEvening());
}
}
Now we can execute the tests and see them fail. This confirms that we haven't made any bad assumptions.
Now we go and write the code which makes the tests pass. Once the tests pass we know that the code works.
public class TimeOfDay
{
private ICalendar _calendar;
public TimeOfDay() : this(new Calendar())
{
}
public TimeOfDay(ICalendar calendar)
{
_calendar = calendar;
}
public bool IsMorning()
{
return (_calendar.GetCurrentTime().Hour < 10);
}
public bool IsEvening()
{
return (_calendar.GetCurrentTime().Hour >= 18);
}
}
So now when we run our tests again we should see all green passing tests.
If we hadn't kept the DateTime class at arms length we wouldn't have been able to easily test the class. The reason we can't is because we are not able to set the value which will be returned from DateTime.Now. Anytime you use classes which magically give you access to something, they better have an interface. If they do not have an interface then you will need to use a solution like this one to wrap the class inside of another one.
One thing that seems to get out of control quickly on a lot of projects I've seen is a tendency for classes to grow to enormous size. This is one problem that seems to turn up at least once in a lot of projects. Why does it happen? Because programmers are lazy. Yes, I said it. We are. I think it is a good thing in a lot of cases. We are "efficiency experts". We pay an up-front cost writing a program so we will have less work to do to solve a problem. By writing the code we save ourselves time. This is one example of this laziness.
When we get lazy we tend to group things together. Since the foo class already has access to types x, y, and z, we can just put this new code in foo. It makes sense, but we're really just making our classes larger. This is why the single responsibility principle is so important. This is one rule important enough that developers everywhere should know about it.
Classes should do one, and only one, task. That is their responsibility. If you need to generate some value, write a class to do that. Don't reuse an existing class. I've seen classes which have gotten so large people don't even know what is in them. I would be scared to make modifications to files like that.
Keep your classes small. It is easier to test individual parts. This is why unit tests are called "unit tests". They test a small piece of the code. If you keep classes small and separate responsibilities among classes it is easier to test. You can break dependencies on the other classes using interfaces, abstract classes, or other things.
Private Methods to discourage use
Sometimes there are methods kept private in a class. Some calculations are kept private because nothing should be calling those methods on this class. This is a good hint that the method belongs somewhere else. If the method is kept private because it doesn't make sense for a user of this class to use it, it belongs somewhere else.
Breaking Classes Apart
The best way to cut large classes down to size is to go through and find pieces which don't belong and are grouped together. Often looking for the collapsible regions of code helps. If you've grouped methods into a region there is a good chance those are related methods and probably belong in a different class.
When you create the new class where you will put these methods, the first thing you should do is test it. This new piece should be very testable since you're pulling it out of the beast. If you test this one piece you'll be able to keep things stable while you pull apart the large class. If you aren't testing each part as you break things up, there is a very good chance you will create bugs in the process.
In my opinion, tests serve two very important purposes. They test to make sure that things work as expected, and they help keep code stable. This stability clamps things down and allows changes to be made. Often times after breaking off separate pieces many refactorings which were hard to find in the large cluttered class become quite obvious. This is why it is so very important to break apart large classes.
In Working Effectively With Legacy Code, the author talks about where to place test classes in your applications structure. He mentions that you should place test classes along side production code in the structure of your application. Why? Well he says that it is good because it helps you navigate between the test classes and the production code easily.
I somewhat agree with him when he says this, because a lot of time is wasted moving between classes. I admit I am one of the people who tries not to mix too much test and production code. I like to keep anything test related at arms length. Why do I do this? Because I believe that everything becomes cleaner and easier to observe when it is separated. I believe there is some reason to keep things aesthetically pleasing, and I certainly believe that keeping them separate will make the system appear a lot less daunting.
Navigating Between Test and Production Code
So I've explained what I like about keeping the two together, but I still haven't made an argument for why I don't need the "navigation" benefits of keeping the two together. The way I handle this is through superior add-ins to my IDE. I use Resharper to give me better navigation. Lately I've become quite fond of this application. If nothing else just for the ability to navigate to classes and files in the solution based on the name alone.
This is incredibly powerful, and it is a quick keyboard shortcut away. It lets you navigate quickly and easily. I like it because it lets me organize how I want to, and I don't need to worry about moving from one assembly to another even. I keep my unit tests in a separate project from any production code. Since I can still navigate quickly, I get all the benefits of both methods.
I think there are a lot of great suggestions people can make for how to code, but at the end of the day you need to make your own choice. Consider people's suggestions, understand why they make them, and certainly adjust them to your own uses.
My opinion is that test classes should go in a separate location. It keeps the production app less cluttered. The application will not deploy test code. If they're separated there will never be any confusion. It would just be terrible if you had a class that actually needed to have the word "test" in the name.
Creating stories to work on is an integral task in agile software development. These stories are what the team of developers will be working on for the iteration. Where do the stories come from? Well, through discussion with the development team, the customer says what he wants. What types of stories does the customer ask for most of the time? The customer asks for epics. What makes them epics? They're just too large.
When writing software in an agile manner it is important to have very small pieces. You want something that can be completed quickly and delivered to the customer. Sure, it might be a small piece that isn't of much value yet, but that is good. The fact that it is small means that you can be constantly finishing pieces of the project. If your stories are too large you'll only be delivering at the end of the iteration. That's just not cool.
Steve Smith wrote a great blog post where he discusses very well how to break epics into vertically sliced stories. One major reason that doing this is of great advantage to you is that you will be able to get feedback from the customer. In Steve's example he talks about a registration page which is loaded with extra data including multiple addresses, contact info, and possibly other pieces. I can see a customer wanting to have something like this. So there are two ways we can approach splitting this up.
Splitting Horizontally
When you split horizontally, you will be delivering the entire solution at the end since each horizontal slice needs to be finished before anything is finished. So for the sake of argument why don't we say that the developer didn't create exactly what the customer wanted the first time. So now at the end of the iteration the developer finds out that the whole process should have been completely different. Now he goes and rebuilds everything in the next iteration because this one is out of time.
Splitting Vertically
Using this method we will quickly have the first small piece done. We can say that it is the ability just to create a user name and password at registration. Now when the customer sees this we get feedback. Maybe everything is fine for this part. We then go do the next part. Maybe we write the address section incorrectly. When the customer sees this he can let us know. Since we know early that there is a problem we can correct it. We may not have everything done at the end of the iteration, but at least we've got the most important parts done.
Since the customer can keep each of these vertical slices in ranking order at the end of the iteration he will have a bunch of working pieces. He will have stuff he cares about even if it isn't all there. If we had found out at the end of the iteration that we needed to make a change we wouldn't have anything done.
Conclusion
It is important to know how to split stories. Sometimes there are pieces of the story which can be vertical slices, but you should try not to have too many dependent tasks. It will make your software development work much faster and better.
A while back I wrote a blog post regarding this topic. In that post I explain that it is safe to use a return statement inside a using block, because the using block will handle the disposing of the defined IDisposable object. This is one truly great ability of the IDisposable interface. It makes it very important to use in my opinion. The using block in combination is very nice, because it handles the disposal for you.
One of my commenter on that post asked me if I was certain that the return statement was safe. He asked this because he couldn't find it in the documents. He also asked me if I had any code showing that this behavior works as I claim it does. I quickly wrote this simple little piece of code which works to demonstrate this behavior.
In my example I have a few things. I have a class which implements IDisposable and all it does to dispose is to write to the console. I then wrote 3 methods which each create and instance of this class in a using statement. One class is normal; it returns after the using statement is complete. The other two end abruptly. One of them returns from within the using statement, and the other throws an exception within the using statement.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Application Starting\n");
Console.WriteLine("Before normal method");
NormalMethod();
Console.WriteLine("After normal method\n");
Console.WriteLine("Before return method");
ReturnFromMethod();
Console.WriteLine("After return method\n");
Console.WriteLine("Before Throw method");
try
{
ThrowFromMethod();
}
catch (Exception ex)
{
Console.WriteLine("Caught the Exception: " + ex.Message);
}
Console.WriteLine("After Throw method\n");
Console.WriteLine("Application Ending");
}
private static void NormalMethod()
{
using (MyDisposable myDisposable = new MyDisposable())
{
// do nothing
}
return;
}
private static void ThrowFromMethod()
{
using (MyDisposable myDisposable = new MyDisposable())
{
throw new Exception("This is the exception");
}
}
private static void ReturnFromMethod()
{
using (MyDisposable myDisposable = new MyDisposable())
{
return;
}
Console.WriteLine("DO NOT WRITE THIS!!!");
return;
}
class MyDisposable : IDisposable
{
#region IDisposable Members
public void Dispose()
{
Console.WriteLine("I am disposing!");
}
#endregion
}
}
This code returns the following result. In this screen shot you should notice that each time it calls the dispose method of the MyDisposable object.
Give the code a shot in a console application, and you will see that the using statement cleans up disposable objects pretty nicely.
Download this sample code as a small C# console application here.
I hope you enjoyed this post. I would also like to thank Lambros for the good comment. I hope to get more feedback from you in the future.