Introduction to Unit Testing
The last couple months I’ve been doing a lot of unit testing at work. A lot. And I’ve been doing it more consistently than I have in the past. The result has been dramatic, not only in the quality of the code that I’m producing, but also in the confidence that I have when making changes to existing code. Even more importantly, however, is the impact that this dedication has had on my knowledge base, as I’ve had to do a lot of reading out of the necessity of creating maintainable, sustainable test suites. This article (and likely a few articles to come) is a breakdown of what I’ve learned so far. If you’ve learned something (or if you know something and you see me learning the wrong things) then I request that you, by all means, please share your knowledge with me and the rest of the world!
What Is a Unit Test?
In a nutshell, a unit test is a chunk of code that tests a small, specific chunk of production code (the System Under Test, or SUT). The Unit Test can assert that the SUT does something, does not do something, returns data (or no data), or exhibits some specific behaviour. Essentially, the Unit Test asserts that the SUT does what it’s supposed to do consistently and predictably.
There’s a subtle but important point in the above that I should emphasize: the SUT is a small, specific chunk of production code. People sometimes want to test bigger chunks of code, or multiple pieces of code (such as testing how a piece of data progresses from Point A through Point B and finally out of Point C). There’s nothing wrong with these types of tests, and indeed these tests (called Integration Tests) should, by all means, be written. But do not confuse them with unit tests, as unit tests are much, much smaller in scope.
Why is Unit Testing Beneficial?
There’s a number of benefits to unit testing, but the majority of them are not immediately noticeable. First and foremost, unit testing can help you detect and avoid defects in your code not only before you ship your code, but before you commit your code to whatever code repository you’re using (you are using source control, right?). On the outset this might not seem like a big deal if you’re writing a small, simple class; however if/when that class gets grows and grows and then gets refactored, those unit tests will be a God send by telling you what you just accidentally broke in the system. From a regression testing and quality standpoint Unit Tests are enormously beneficial.
Well written unit tests (and unit test suites) also act as documentation which illustrates what the SUT is and is not supposed to do, and also how the SUT is used. In essence, the tests are the specifications of the SUT. They act as examples, and these examples are significantly important to the people that will inherit your code after you’ve left your current employer (which, be honest, is inevitable). In fact, they’ll even help you when you return to that class 8 months after you wrote it because somebody in marketing wants your Duck class to be able to play the banjo. Having the ability to review your code, how it works, how a programmer should interact with it etc. all from a single location, without having to do a Find All across tens, hundreds or thousands of code files is pretty convenient. Enjoy The Convenience Of Knowing Where To Look! Yay Lazyness!
There are about a zillion other benefits, but I’ll only mention one more because it ties into a bigger concept of unit testing; under certain conditions unit tests can help you design better, leaner code; the practice of what’s called Test Driven Development. The idea behind TDD is that you define, via tests, what the SUT needs to do, and then you write the least amount of code possible in the SUT to pass the tests.
What Are Some Unit Testing Cons
Not all that glitters is gold, and while the benefits and advantages of unit testing are enormous, they do come at a price.
For starters, unit tests aren’t free. At the end of the day, a Unit Test is software, and that software has to get written by a developer, and developers cost money. If you’re going to use TDD or implement unit tests at a later date you will have to take that into account when making estimates. If your biggest goal is to hammer out as much code as possible in the absolute shortest amount of time possible, quality and scalability be damned!, than unit testing might not be for you. However, if you’re working on a long term project (either for yourself, your company, or somebody else’s company), the cost of adding on some time for a higher quality product is a no brainer (hint: do it).
Another con is one you’ll notice pretty quick: unit test organization (and unit tests themselves) can get complex. Just like production code is difficult to write in a sustainable and maintainable way, test code can be even more difficult. The principles and strategies that exist in writing “real world” code are still applicable to test code. You will experience the same heart-ache, frustration, and demoralization of poorly structured tests as you do with poorly structured production code.
Many people don’t take this into account when writing unit tests, and when things start to go awry and the various smells of unit tests start to rear their ugly head, it’s easy to just say “forget it” and drop unit testing because “it isn’t worth it.” But these test smells, much like code smells, can be avoided (or at least minimized) by learning from the mistakes of others. The book xUnit Design Patterns – Refactoring Test Code is the holy bible of unit testing. If you’re a beginner or experienced TDDer, this book should be on your shelf. However, if you’re like me, you’ll find the book is right next to your keyboard – there’s no sense putting it back on the shelf! I consult it daily!
Don’t treat unit tests as a second class citizen; just because they aren’t getting shipped doesn’t mean they take a back seat to basic OOPL principles. Be kind and thoughtful to your unit tests, and they will repay you like, ten fold, dude.
Just do Them!
Just like everyday production code, there can be many gotchas to unit testing; but they’re nothing a bit of reading, research, and careful design can’t take care of. The long term benefits of unit testing are enormous. The project that I’m currently working on has only been under development for 2 months, and we’re still learning the discipline of unit testing, but I already have 300 tests (77 of them are on a small, single component of the code). That’s 300 tests that will not only let me know when something no longer works, but if my tests are structured well, will tell me exactly where the something went wrong.
This article was a (very) brief introduction to Unit Testing. In my next article I’ll outline for you the different components of a unit testing framework, and hopefully from there we can start building some examples.
Stay tuned!
Do you have experience with TDD (or Unit Tests in general)? Share your knowledge and experience in the comments!
C# – Overloading an Enum’s ToString()
Enumerations can sometimes be useful. It’s true, I think that you can refactor enum’s into big-I-Interfaces a lot of the time, but enums do have their place. There are 2 things that I don’t like about enums, however:
- They eventually lead to lots of if-this-than-that-else-blah-otherwise-holycrap conditional hell (hence refactoring into big-I-Interfaces), and
- You can’t overload the ToString() method
If you’re stuck using an enum, point 2) can become pretty valuable. For example, in my current case, I have an enumeration that denotes the different styles available to an image. These styles are only accessed at runtime, and can be mixed and matched using bitwise operations. Eventually, these styles get rendered from an enum into a string stored in an XML file — it is here where overloading the enum’s ToString() method would come in handy. Unfortunately, out of the box, all you’re capable of doing is a .ToString() on the enum, which will render several different possibilities depending on how you defined your enum. Fortunately C#’s extension methods and Custom Attributes allow us to get around all that.
The solution I came to was to create a Custom Attribute which would decorate each enum value. This custom attribute (called EnumDescription) has a single property called “Text” which will be used via some magical extension methods.
public class EnumDescription : Attribute
{
public string Text
{
get { return _text; }
} private string _text;
public EnumDescription(string text)
{
_text = text;
}
}
Pretty simple. I then decorate my enum values with the EnumDescription attribute, and provide whatever description I want. In our case, I’ll just create a simple RGB enum with english constant names, but french descriptions (cause, you know, I’m cultured like yogurt).
[Flags]
public enum RGB
{
[EnumDescription("rouge")]
Red = 0,
[EnumDescription("vert")]
Green = 1,
[EnumDescription("bleu")]
Blue = 2
}
The last component of this excercise is to create an extension method that allows us to easily use the EnumDescription attribute without having to write reflection lines whenever we need. The beauty of creating an extension method for this is that the enumeration will get intellisensed with our extension method and the developer won’t need to know of some obscure static method on some static class.
public static class EnumExtensions
{
public static string ToDescription(this Enum enumeration)
{
Type type = enumeration.GetType();
MemberInfo[] memInfo = type.GetMember(enumeration.ToString());
if (null != memInfo && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(typeof(EnumDescription), false);
if (null != attrs && attrs.Length > 0)
return ((EnumDescription) attrs[0]).Text;
}
return enumeration.ToString();
}
}
In the method above we check to see if the enumeration in question is decorated with an EnumDescription custom attribute. If it is than we use the Text description contained within that attribute, otherwise we’ll fall back on whatever .ToString() returns.
In the end, from the point of view of the developer consuming the API, this is what it looks like:

Of course, the last thing we need to do is to create an extension method that uses the EnumDescription in the opposite direction (similar to Enum.Parse), but considering I don’t actually need that code just yet, I haven’t written it. Next time!
Or, if you don’t want to wait, impress me by applying for 1 of our jobs, and submit your answer as part of your application!
Usability is King
When it comes to the purity of developing software for people, there’s only 2 things that matter:
- The people find the software useful, and thus use it
- The people enjoy using the software because the software is easy to use.
I’m not going to go on a long diatribe about usability, how Microsoft doesn’t get it and Apple does, or how hard good usability is to create. I’m not even going to tell you that good usability is just 20 feet away from you, or if you’re one of the lucky few developers, a girlfriend away. We all know that research into good usability is affordable, timely, requires just a little bit of creative thinking and doesn’t require super duper expensive laboratories , so I’m not going to bore you with that.
Instead, what I am going to bore you with is this quick and easy statement: There is no excuse for terrible usability, especially in the most simple of scenarios. No sir, you can try and blame the user, or show somebody that it’s “simple” (followed by 17 mouse clicks), or tell somebody that it’ll make sense “after they get their head around it”, or that they “just need to re-read it because they just don’t get it”, sure, go ahead. But at the end of the day it’s all you, baby, with the proverbial egg on your face. How’s it taste?
Some of these issues are so overwhelmingly glaringly embarrassing it’s sad. This morning, while I was grabbing stuff off my Samba share from my Vista laptop, Microsoft thought it’d be a good idea to confirm what, exactly, it was that I wanted to do.
Well, I’d like to copy them, of course! So I’ll just – wait… uh… wha? There is no excuse for something like the above dialog. Seriously. That’s just downright silly. Maybe if English is your 3rd language, and you just picked it up last week, and you’re writing software for a Western client and you don’t have access to a single person that speaks English at a 2nd grade level, than yes, I suppose you have an excuse. But Not if you’re the world’s biggest software company… hell, not even if you’re the mom & pop shop on the corner.
One of the things that I love about where I work is that big, hulking, gentle Polish giant Allan Wolinski. Sure, the guy never updates his blog (hint), but he’s always updating my Jira list of assigned issues with really kick ass ideas surrounding Usability. I couldn’t possibly write a crappy application working with Allan – he just simply would not allow it.
So to all the people out there who take 5 minutes of their day and quickly hand sketch their ideas on paper and kidnap a coworker and ask them what they think – I solute you. For it is you that is making computing better by not asking me open ended questions and only accepting 1 of 2 closed answers that make no contextual sense.
What are some of your favourite little (un)Usability whoopsies that you’ve stumbled across?
