In this post I will introduce you to JustCode and the NUnit testing framework. I’ll also demonstrate the basic TDD workflow from introduction of the first requirement all the way through to writing your first test. At the end of this post you will have a test based on a given requirement. In the next post we will work through the rest of the workflow and make the test pass.
There are a few tools that you will need to work through the examples in the posts over this series. First and foremost you will need Visual Studio. I will be using Visual Studio 2013 Preview for the examples, but if you are using Visual Studio 2012 you will able to follow along just fine. I will be making extensive use of NuGet throughout this series, so if you are using Visual Studio 2008 you can try following the steps in this post to enable NuGet support in that version. If the advice in the post doesn’t help you or you’re using Visual Studio 2005 you will need to download the libraries and add the references to the projects manually. If you do not have Visual Studio you can get a free version of Visual Studio 2012 Express from Microsoft.
The easiest way to write unit tests in C# or VB.NET is to use a unit test framework. There are several unit test frameworks for .NET, but for this series I’ll be using NUnit. While not the only unit testing framework available for unit testing in .NET, NUnit is probably the most popular. NUnit is fully featured, widely used and enjoys a large amount of community support. This is not to say that other unit testing frameworks (such as MS Test, MbUnit and xUnit) are not supported or that there is something wrong or lacking in these frameworks. But these other frameworks don't enjoy as large a user base as NUnit. In your travels as a TDD developer you are almost certain to encounter NUnit. If you are using one of those other frameworks they function in a very similar way to NUnit and the skills you learn here with NUnit should transfer over very nicely to those other frameworks.
Before we get too deep into code, we should start be gathering our requirements and making sure we have a good expectation of what problem we are attempting to solve and how best to solve it. Our requirement for this sample is:
“Create a library method that takes in a sentence and a single character as parameters. The method should return a number that indicates how many times the character appears in the sentence.”
This seems easy enough. We have an idea of what the expected inputs and outputs are as well and what’s needed seems pretty straight forward. Now that we have our tools in place and our requirement has been defined we can work on setting up our solution and project in Visual Studio. To do this I open Visual Studio and from the File menu select New –> Project (or I can simply use the keyboard combination of Ctrl + Shift + N). On the “New Project” window I want to open “Other Project Type” in the “Templates” section on the left and select “Visual Studio Solutions.” Usually there will only be one project type available and it will be called “Blank Solution” as shown in Figure 1:
Figure 1 – Creating a new blank Visual Studio solution
Select the Blank Solution, specify a name (I’m using ThirtyDaysOfTDD, but you don’t have to) and make sure the Location is correct. When all of that is done press OK and you should have a Visual Studio solution with nothing in it, as shown in the Solution Explorer (Figure 2)
Figure 2 – An empty Visual Studio solution.
Next I’ll need a project to store my unit tests in. You should keep your unit tests in a separate project than your application code since you will not be deploying your tests, just your application code. This also helps keeps your solution organized. Furthermore, I like to keep my unit tests separate from my integration tests, load tests and any other type of test I may have. Again, this helps keep things organized and easy to find when you need them.
To create a project for my unit tests, I right-click the ThirtyDaysOfTDD solution in the Solution Explorer and Add –> New Project… When I do this I’m presented with the “Add New Project” window shown in Figure 3:
Figure 3 – Adding a project for the unit tests
As you can see above, I’ve selected a C# Class Library and named it “ThirtyDaysOfTDD.UnitTests”. I left the default Location. I click the OK button and my project is created, as you can now see in the Solution Explorer in Figure 4:
Figure 4 – The project that will contain the unit tests
Since Visual Studio was thoughtful enough to provide us with a starter class (Class1) we’ll go ahead and use it, but first I want to rename it. I’ve decided that for this requirement I’m going to create a class for the method called “StringUtils.” In your company or project you no doubt have some sort of naming standards or policy describing where functionality is implemented based on what it does (even if it’s not formal), and you should try to adhere to these local standards at all times. But for this demo, calling the class StringUtils is good enough, so that’s what I’m going to do. Based on this, I’m going to rename Class1 to StringUtilsTests. The current code looks like this:
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Text;
5: using System.Threading.Tasks;
7: namespace ThirtyDaysOfTDD.UnitTests
9: public class Class1
JustCode makes renaming classes very easy and quick. To use JustCode to rename this class I will put my cursor on the class declaration (line 9) and press F2. JustCode will highlight the class name and show me a list of options for renaming in the lower left corner as shown in Figure 5:
Figure 5 – Renaming a class with JustCode
By using the JustCode rename functionality I not only renamed the class, but I also renamed the file in the same step, as seen in Figure 6:
Figure 6 – My class has been renamed
Now that that’s done the next step is to add NUnit to the unit test project. You can certainly download and install NUnit from the link provided above, and then add the reference to the NUnit assembly to the ThirtyDaysOfTDD.UnitTests project manually. If you are using Visual Studio 2012 or higher you can use NuGet to install NUnit. To get NUnit with NuGet I go to the Tools –> Library Package Manager –> Manage NuGet Packages for Solution menu. This brings up the “Manage NuGet Packages” window as shown in Figure 7:
Figure 7 – NuGet Package Manager
In the NuGet Package Manager window, I want to select “All” under the “Online” section on the right side of the window. The in the search text box, located on in the upper right corner of the window I type “nunit” and hit Enter. It will take a few seconds for the search to complete, after which I can see NUnit listed in the search results. There are many items that will turn up in this search, but to be clear I specifically want the one that only says “NUnit” (the item highlighted in Figure 7); not any of the other NUnit extensions. Once you’ve located the correct item in the search results, click the “Install” button next to it. You will then see “Select Projects” dialog like the one in Figure 8. This allows me to specify which projects you would like the package, in this case NUnit, added to. You want to make sure that you have ONLY selected your test project(s) in this dialog (your non-test projects do not need a reference to NUnit). In this case we only have the one project, so picking the correct one is easy:
Figure 8 – Where do you want your package installed?
This downloads the NUnit library and references it in my unit test project as shown in Figure 9:
Figure 9 – NUnit has been added to the test project
Now that I have a unit test project setup and have added a reference to the NUnit framework to it I can start writing my first test. But before that I write my test I need to tell NUnit that my StringUtilsTests class will contain my unit tests. I do that using the TestFixture attribute as shown here on line 9:
10: public class StringUtilsTest
(get sample code)
The TestFixture attribute is part of the NUnit library. When the unit test project is compiled down to an assembly, NUnit will look for classes that are decorated with the TestFixture attribute and look for tests inside those classes. To use the TestFixture attribute I will need to include a using statement for the NUnit namespace. If I’m using JustCode I can put my cursor on the TestFixture attribute and press Ctrl + ~ to bring up the JustCode Visual Aid Menu as shown in Figure 10:
Figure 10 – the JustCode Visual Aid Menu
JustCode can easily add any missing usings for me. I’ll select the “Add using for ‘NUnit.Framework’” menu item and JustCode will add a using statement for the NUnit.Framework namespace for me (line 3):
2: using System.Linq;
3: using NUnit.Framework;
5: namespace ThirtyDaysOfTDD.UnitTests
8: public class StringUtilsTest
JustCode also removed the namespaces I wasn’t using. This helps my code from being cluttered and makes it easier to read.
Based on the requirement, I can pretty easily come up with a simple test that tests the “happy path” (a scenario where all inputs are right in the middle of the acceptable range and the method is expected to execute in its simplest and most straightforward form). In this case I can define my test as:
I want to pass in the sentence “TDD is awesome!” and the character “e” and my result should be two.
Turning back to my code, I need create a method that exercises this test. I’ll create a method for this test called ShouldBeAbleToCountNumberOfLettersInSimpleSentence that takes no arguments and is of type void:
10: public void ShouldBeAbleToCountNumberOfLettersInSimpleSentence()
I know that the name of the test method is kind of long, but that’s OK. First and foremost the name of a test should be descriptive. You should, to the best of your ability, describe the condition you are testing and what your expected result is. This isn’t always easy to do, but you should try to get as close as you can. Don’t worry about long method names. For one thing you are probably not going to call this method directly yourself, the test runner will run it (more on test runners in the next post). Another reason I would rather have a long descriptive name is that as this application grows and the number of tests increases I will not remember what each test does off the top of my head. Having a well named test will help me down the road when this test is one of 500 tests in my application and it starts to fail. Based on the name I’ll already have a pretty good idea what’s going wrong. Finally, long descriptive names can help me ensure that I’m writing the correct code. Business Analysts and QA Testers may not be able to read my code, but they can read a descriptive test name and have a pretty good idea of how well I have understood the specification in question.
The next step is to identify this method as an NUnit test. I do that by adding the Test attribute to the method declaration as seen here on line
11: public void ShouldBeAbleToCountNumberOfLettersInSimpleSentence()
Patterns in software development are very helpful. They have a way of taking a complicated problem and boiling it down to a few (somewhat) simple steps. The best patterns are the ones that once you get used to them just feel natural, as if you’re not “following a pattern” so much as “doing it the way you’re supposed to.” When it comes to writing unit tests, the Arrange, Act, Assert patter (AAA) has become the logical and preferred standard.
AAA reflects the three steps that all unit tests carry out. Arrange refers to setting up your test by defining the inputs and expected outputs. I can do that for my test by declaring the input sentence, the character I’m looking for and the expected result as local variables:
1: public void ShouldBeAbleToCountNumberOfLettersInSimpleSentence()
3: var sentenceToScan = "TDD is awesome!";
4: var characterToScanFor = "e";
5: var expectedResult = 2;
In addition to declaring my local variables for testing, I’ll also need an instance of the class I’m testing (line 10):
6: var stringUtils = new StringUtils();
Next in the pattern is Act, which the method that is being tested is called and the result captured. At this time I’m also going to decide what my new method (the one required by this requirement, and by extension this test) is called. I think FindNumberOfOccurences is a good descriptive name, so that’s what I’ll go with. I call the method and capture the result on line 8:
8: int result = stringUtils.FindNumberOfOccurences(sentenceToScan, characterToScanFor);
(get code sample)
Finally we come to Assert. In this phase we are verifying that the result we received from our method under test matches the expected result. We do this using an “Assert” method. The Assert class is a static class that is part of the NUnit framework and provides a collection of methods to evaluate data and signal that a test has either passed, failed or the result was inconclusive. For this test I’ll call the AreEqual method on the Assert class which evaluates two values. If the values are not equal NUnit signals that the test has failed and execution stops with the failure result reported. If the two values are equal the test is allowed to proceed. This enables you to have multiple asserts in the same test. If a test finishes without a failure message being sent NUnit considers the test as having passed. There are other methods on the Assert class and I’ll cover them in upcoming posts.
We covered quite a bit of ground in this post. I’ve outlined the various requirements for the version of Visual Studio you will be using. I discussed the need for a unit testing framework and introduced you to the basics of NUnit. I discussed Visual Studio productivity tools, specifically Telerk’s JustCode and how it can make your software development much easier and more efficient. Finally we wrote our first test. The next post will be dedicated to making this first test pass, and writing our next test.
Continue the TDD journey:
Copyright © 2017, Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
Progress, Telerik, and certain product names used herein are trademarks or registered trademarks of Progress Software Corporation and/or one of its subsidiaries or affiliates in the U.S. and/or other countries. See Trademarks or appropriate markings.