Click here to Skip to main content
15,867,704 members
Articles / DevOps
Tip/Trick

The (Probably) Simplest Intro to Visual Studio Unit Testing Ever Written

Rate me:
Please Sign up or sign in to vote.
4.00/5 (4 votes)
25 Feb 2016CPOL4 min read 13.3K   9   11
This is a bare-bones, step-by-step tutorial into getting your first test project set up in a Visual Studio solution that already has a project that you want to test

Toe-dipping into the MS Test Waters

Note: This is an example of "test second" (not "test-first") methodology.

Here is all you need to do to get started with using a Testing project in Visual Studio (2013, that is, although it probably works the same, or near enough to the same, in other versions of VS so as to be nary worth a note):

Right-click a solution which already contains a project that you want to test, and select Add | New Project...Select Visual C# | Test

Give the test project the same name as the existing project it will test + ".Tests"; e.g., if the project you are going to test is named "RoboReporter", you could name it "RoboReporter.Tests". Of course, you could really name it just about anything you want, even "YourMamaWearsCombatBootsUsedToBeConsideredAPejorative.ThisIsNotATestNoReallyItIsInFact" - but why would you?

Your main app doesn't need to know about the Test project, but the Test project does need to know about the main project, so add a Reference to the project you're going to test. Right-click References | Add Reference..., and select Solution | Projects | and then your project (such as RoboReporter).

Now you are at the point where you can add test code, in the "UnitTest1.cs" file that has been created for you (you can rename it if you want and/or add another class). If you opt to change the name to make its purpose clearer (recommended), you can name the class "UtilitiesTest" or "TheKalamazooKazoosPlayAtTheZoosAndGetPooOnTheirShoes" or whatever floats your dinghy.

Microsoft [Rocks Like a Hurricane Shelter from the Storm] Windows

Add a "using Microsoft.VisualStudio.TestTools.UnitTesting;" to the top of the class if it's not already there, and also a reference to the main project (such as "using RoboReporter;")

Add a "TestClass" attribute above the class name so that your class looks like this (assuming your app is named "RoboReporter" and you named the class "NUnitTest":

C#
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RoboReporter;

namespace RoboReporter.Tests
{
    [TestClass]
    public class UtilitiesTest
    {
    }
}

Add a method that will instantiate a "foreign" class in your project and call one of its methods. First, add a "TestMethod" attribute to the method so that it looks like this:

C#
[TestClass]
public class UtilitiesTest
{
    [TestMethod]
    public void TestGetNextWeekday()
    {
    }
}

Add some code to test your assumptions about the method you're testing, and add an "Assert" statement to the bottom of the method, like so:

C#
public void TestGetNextWeekday()
{
    DateTime pseudoRandomDate = new DateTime(2016, 02, 24);
    DayOfWeek dow = DayOfWeek.Monday;
    DateTime retVal = RoboReporterConstsAndUtils.GetNextWeekday(pseudoRandomDate, dow);
    // The value returned should be 2/29/2016
    DateTime expectedVal = new DateTime(2016, 02, 29);
    Assert.AreEqual(expectedVal, retVal);
}

Now your entire test class should look something like:

C#
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RoboReporter;

namespace RoboReporter.Tests
{
    [TestClass]
    public class UtilitiesTest
    {
        [TestMethod]
        public void TestGetNextWeekday()
        {
            DateTime pseudoRandomDate = new DateTime(2016, 02, 24);
            DayOfWeek dow = DayOfWeek.Monday;
            DateTime retVal = RoboReporterConstsAndUtils.GetNextWeekday(pseudoRandomDate, dow);
            // The value returned should be 2/29/2016
            DateTime expectedVal = new DateTime(2016, 02, 29);
            Assert.AreEqual(expectedVal, retVal);
        }
    }
}

Note: Besides "Assert.AreEqual()", there are other "Assert"s you can use to test your methods, such as:

  • Assert.NotEqual
  • Assert.IsFalse
  • Assert.IsTrue
  • Assert.Null
  • Assert.NotNull

Finally, run the test to verify that your assumption (assertion) is correct; select Test | Run | All Tests (or mash Ctrl+R, A). If you don't see the results in the Test Explorer window, you can by selecting Test | Windows | Test Explorer. If the test passes, you will see a green arrow icon next to your test; if it fails, you will peer bemusedly at a circular "red X" icon. To test that, you can provide a bogus answer as the expected answer such as changing "expectedVal" to something other than "DateTime(2016, 02, 29)" such as by changing the "29" to "28" or something like that.

If you want to test the same method as in the example above, it is:

C#
// from Jon Skeet (http://stackoverflow.com/questions/6346119/datetime-get-next-tuesday)
public static DateTime GetNextWeekday(DateTime start, DayOfWeek day)
{
    // The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
    int daysToAdd = ((int)day - (int)start.DayOfWeek + 7) % 7;
    return start.AddDays(daysToAdd);
}

This is just scratching the surface, but it shows how test methods can be incorporated into your Visual Studio solutions; keeping this tip brief holds to the attestation (No pun intended) that this is the shortest of all Test toedippings ever seen by modern (not to mention neanderthal) man (not to mention woman).

Note: To be able to test methods with the "internal" access modifier (to avoid changing them to "public"), add the following to the \Properties\AssemblyInfo.cs file:

C#
[assembly: InternalsVisibleTo("RoboReporter.Tests")]

(this assumes your test project is named "RoboReporter.Tests").

Side Dishes

A side benefit of viewing the tests in the Test Explorer is it tells you how long it takes for each test to run, which gives you a good idea of which methods may need to be revisited/refactored for performance tuning.

There are a couple of more side benefits that accrue to you when adding Test projects to your solutions: It (practically) forces you to write separate methods to call from your event handlers, rather than putting the event handling code right there (it's hard to call an event handler from a test project, for which you would have to pass a sender and event args). It's a good thing to do it that way, anyway (call separate methods from event handlers), because you may need to call that code from elsewhere, anyway (not just from the event handler - other actions can require the same code to run). This is, of course, if you don't actually use "sender" and the event args in your code.

Who Let the Bugs Out?

If a test is failing and you dont' know why, put a breakpoint in it and then select Test | Debug | All Tests or just mash Ctrl+R, Ctrl+A

Now you can take it from here and test to your heart's contentiousness.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder Across Time & Space
United States United States
I am in the process of morphing from a software developer into a portrayer of Mark Twain. My monologue (or one-man play, entitled "The Adventures of Mark Twain: As Told By Himself" and set in 1896) features Twain giving an overview of his life up till then. The performance includes the relating of interesting experiences and humorous anecdotes from Twain's boyhood and youth, his time as a riverboat pilot, his wild and woolly adventures in the Territory of Nevada and California, and experiences as a writer and world traveler, including recollections of meetings with many of the famous and powerful of the 19th century - royalty, business magnates, fellow authors, as well as intimate glimpses into his home life (his parents, siblings, wife, and children).

Peripatetic and picaresque, I have lived in eight states; specifically, besides my native California (where I was born and where I now again reside) in chronological order: New York, Montana, Alaska, Oklahoma, Wisconsin, Idaho, and Missouri.

I am also a writer of both fiction (for which I use a nom de plume, "Blackbird Crow Raven", as a nod to my Native American heritage - I am "½ Cowboy, ½ Indian") and nonfiction, including a two-volume social and cultural history of the U.S. which covers important events from 1620-2006: http://www.lulu.com/spotlight/blackbirdcraven

Comments and Discussions

 
GeneralTestability of code Pin
John Brett1-Mar-16 1:09
John Brett1-Mar-16 1:09 
GeneralRe: Testability of code Pin
B. Clay Shannon1-Mar-16 3:35
professionalB. Clay Shannon1-Mar-16 3:35 
GeneralMy vote of 4 Pin
Gaston Verelst29-Feb-16 2:08
Gaston Verelst29-Feb-16 2:08 
GeneralRe: My vote of 4 Pin
B. Clay Shannon29-Feb-16 2:22
professionalB. Clay Shannon29-Feb-16 2:22 
GeneralRe: My vote of 4 Pin
Gaston Verelst29-Feb-16 3:02
Gaston Verelst29-Feb-16 3:02 
GeneralMy vote of 4 Pin
dmjm-h26-Feb-16 10:52
dmjm-h26-Feb-16 10:52 
GeneralRe: My vote of 4 Pin
B. Clay Shannon26-Feb-16 10:56
professionalB. Clay Shannon26-Feb-16 10:56 
Question? Small correction required Pin
Garth J Lancaster25-Feb-16 11:50
professionalGarth J Lancaster25-Feb-16 11:50 
AnswerRe: ? Small correction required Pin
B. Clay Shannon25-Feb-16 11:56
professionalB. Clay Shannon25-Feb-16 11:56 
Questionhow deos this code works?? Pin
Waseem Wasem25-Feb-16 11:07
Waseem Wasem25-Feb-16 11:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.