Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / DevOps / unit-testing

Introduction to Unit Testing with: MS tests, NUnit and Fluent Assertions.

4.60/5 (20 votes)
12 Jun 2014CPOL9 min read 114.5K   1.4K  
Different ways of achieving unit testing for your projects

The above files are were built with VS 2013 targeting .Net 4.5. The Bigger files also include the NuGet packages that we'll use.

NOTE for NUnit 3:

  • As of mid April 2016, the new external NUnit Gui runner is still not out. It seems to be in alpha versions. You can find the GitHub project here.
  • Seems like the "Result = ..." syntax in the TestCase was changed to "ExpectedResult =..." . Just keep this in mind.

Introduction

This article will show you the basic of using MS Unit Test ,NUnit & Fluent Assertions. I'm not intending to cover everything, but rather show you some options so you can choose the one that suits you best.

Quick reference:

Our main project

Since nobody cares about project that nobody cares about, I took the time to see what's trending around the world according to google, and we're going to use that, since (statistically speaking) it must interest you as well.

Our main project is just a console project, with one method, and all it does is print out the top 3 trending results from google trending page. Here's the code:

C#
public class TrendingRunner
{
    static void Main(string[] args)
    {

       Console.Out.WriteLine("This will show what's trending according to {0}"
           , "http://www.google.com.au/trends/topcharts" );
       Console.Out.WriteLine("Hit any key to see the next result.");
       Console.Out.WriteLine("");

       for (int iteration = 1; iteration < 5; iteration++)
       {
           Console.Out.WriteLine("What's trending top list number {0}: {1}."
               , iteration
               , WhatsTrending(iteration)
               );

             Console.ReadKey(true); // wait for a key press
         }
    }

    /// <summary>
    /// Will return the top 3 from : http://www.google.com.au/trends/topcharts
    /// </summary>
    /// <param name="anIndex">Which index to return</param>
    /// <returns>A string holding the interest @ index "anInedx"</returns>
    public static string WhatsTrending(int anIndex)
    {
     string answer;
     switch (anIndex)
     {
        case 1:
            answer= "Paul Walker";
            break;
        case 2:
            answer= "Cory Monteith";
            break;
        case 3:
            answer= "RoyalBaby";
            break;
        default:
            answer = "Choose an index between 1 or 3, or go and search it yourself.";
            break;
     }
     return answer;
    }
}

MS Unit Tests

Now we'll add a new project to our solution. Right click on the solution and then : -> add -> add new project, Select Visual C#, then Test, then Unit Test Project.

Image 1

Next, right click on the references under the new project, click add reference, select solution, and add your console project, so you can access it easily and test it.

Image 2

Great ... you should have something like :

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

namespace MSTest
{
    [TestClass]                    // Defines a testing class
    public class MSTestExample     // name, like any other class
    {
        [TestMethod]                          // this mark the method as a test
        public void Test_Trending_MSTest_OK() // method name, like any other
        {
            /*
             * your test goes here.
             */
        }
    }
}

(if you're missing the "using Trending;" feel free to add it, it'll save you grief later.)

What will do is add our (very basic) test in the Test_Trending() method. My convention is to start testing methods with Test_ and follow by the method test I'm testing (UpperCamelCase). In this example, I've also added which FrameWork is being used (MS Test , NUnit), and whether or not it's Fluent or not (more on this later)

Now our test looks like :

C#
[TestMethod]               
public void 

Test_Trending_MSTest_OK()
{
    var result = TrendingRunner.WhatsTrending(1);
    Assert.AreEqual("Paul Walker", result);
}

Now either select Test -> Run -> All Tests , or hit CTRL+R , A to run all your tests. (one in our case).

Image 3

You should now see :

Image 4

If you would have managed to have a typo, or assuming you have real logic and the result is not what you're expecting, you'll see:

Image 5

Note: There's not much extra info in the MS Test failure case.

Congratulations. You are a certified Unit Tester (Terms and conditions might apply ).

A different option: NUnit

(Note: The original was written when NUnit 2.6x was out. Currently 3.2 is out, so im updating this to be a bit more relevant)

After working hard in achieving my own private Unit Tester certification, why would you want to continue? That's up to you. Euclid would have given you a coin according to legends*, but I'm all out of coins.

The benefit I find in using NUnit is having multiple tests under the same Test method. Let's explore this idea. Assuming we want to make sure that our unit tests cover all execution paths, we might add conditions to our test method, so it might be looking like:

C#
[TestMethod]               
public void Test_Trending()
{
    var result = TrendingRunner.WhatsTrending(1);
    Assert.AreEqual("Paul Walker", result);

    result = TrendingRunner.WhatsTrending(2);
    Assert.AreEqual("Cory Monteith", result);

    result = TrendingRunner.WhatsTrending(3);
    Assert.AreEqual("RoyalBaby", result);
}

That's ok, and it'll pass, but some purists will frown upon you and say you should only have 1 assert per test. So, we can either ignore, them, or break our tests into three methods, and this is where things start to get ugly, and repetitions (and the inevitable bugs from copy pasting the around) start to bog you down.

For NUnit 2.6.x:

We're going to add NUnit to our project (I've created another project for this, but you can reuse the previous). Goto Tools -> Nuget Package Manager -> Manage NuGet Packages for Solution, Select the "Online" option on the left, type "NUnit" in the top right, and the first result shall be what you want. You probably want to install the Test adapters as well, so you can run the tests from inside Visual Studio. Otherwise, you'll need to run them with NUnit external application (which has it's own benefits, but we'll leave it for another article).

Image 6

For NUnit 3.2:

It's a very similar process. Using VS 2015 the NuGet manager changed a bit (some will argue that it wasn't for the best). First install the new NUnit for your testing project:

Image 7

Second, you'll have to install the NUnit 3 Test adapter. You can do this from the  Tools -> Extensions and Updates window

Image 8

Back to our NUnit tutorial:

Note: When asked to which projects you want to add NUnit, select only the test project you need (no point in adding the dlls to the console project for example).

The difference in syntax isn't big, your new tests will look like this:

C#
public class NUnitTest
{
    [TestCase]                  // this mark the method as a test in Nunit
    public void Test_Trending()
    {
        var result = TrendingRunner.WhatsTrending(1);
        Assert.AreEqual("Paul Walker", result);
    }
}

So far, nothing ground breaking. The above will run (assuming you installed the adapter) from VS just like the normal tests.

Here's where NUnit extras kick in. We'll modify the return value from void to whatever it is our method returns, we'll add a parameter to the test method, and now we can have multiple tests defined as decorations above the method. For example:

C#
//  --------------------      NUnit 2.6.x     --------------------              
[TestCase(1, Result = "Paul Walker")]
[TestCase(2, Result = "Cory Monteith")]
[TestCase(3, Result = "RoyalBaby")]
public string Test_Trending(int anIndex)
{
    return TrendingRunner.WhatsTrending(anIndex);
}

//  --------------------     NUnit 3.2     --------------------              
[TestCase(1, ExpectedResult = "Paul Walker")]
[TestCase(2, ExpectedResult = "Cory Monteith")]
[TestCase(3, ExpectedResult = "RoyalBaby")]
public string Test_Trending(int anIndex)
{
    return TrendingRunner.WhatsTrending(anIndex);
}

Note: Syntax seems to have changed a bit. The downloads are still correct, since they use 2.6.x, and if you're following the instructions, just make sure you change Result with ExpectedResult.

Now, our test is called three times, with different parameters, and it's easy to see what's the expected result. Note that you do not use the Assert now, you just return, and let NUnit take care of the rest.

If your test passed, you'll see:

Image 9

And if it failed:

Image 10

Note: You do get more info here than what you'll get in MS tests, which is nice and will help you figure out what's wrong.

I personally like to add a Console.Out.WriteLine to my tests. The reason is that I like to have visual feedback in addition to the green(pass) / red(fail) results:

C#
[TestCase]                  
[TestCase(1, Result = "Paul Walker")]
//...
public string Test_Trending(int anIndex)
{
    var result = TrendingRunner.WhatsTrending(anIndex);
    Console.Out.WriteLine("Call \t-> \tresult :\r\n  {0} \t-> \t\"{1}\""
                        , anIndex
                        , result );
    return result;
}

Clicking on the "output" under the test will show you whatever was written to the console: in this case:

Image 11

Fluent Assertions

Last, but not least, I want to talk about fluent assertions.

The idea behind this is to have a BDD** fluent sentence asserts. It is easier on the eyes and makes more sense, if you have a strong issue with the syntax of the previous options.

I've created a third test project called MSFluent but you can simply reuse the original MS test project. Head to NuGet package manager, and hunt down "fluent assertions" (If you don't remember how, it's the same steps as above for NUnit, but simply search online for fluent assertions)

Note: You can add it to NUnit as well. I'm using MS tests here, because I've used the multiple cases with return values in NUnit.

Now our test methods look like this:

C#
[TestMethod]
public void Test_MSTest_Fluent_OK()
{
    var result = TrendingRunner.WhatsTrending(1);
    result.Should().Be("Paul Walker");

    // another fluid assertion
    result.Should().NotBeEmpty("because it should have a value");
}

[TestMethod]
public void Test_MSTest_Fluent_Fail()
{
    var result = TrendingRunner.WhatsTrending(1);

    result.Should().Contain("Paul);     // Will pass
    result.Should().Be("Paul Talker");  // Will fail because of typo
}

For more examples and cool things, head to fluent assertions homepage their new github homepage. Here are some examples of what you can do with strings:

C#
string theString = "";
theString.Should().NotBeNull();
theString.Should().BeNull();
theString.Should().BeEmpty();
theString.Should().NotBeEmpty("because the string is not empty"); 
theString.Should().HaveLength(0);
theString.Should().BeBlank(); // either null, empty or whitespace only
theString.Should().NotBeBlank();
theString = "This is a String";
theString.Should().Be("This is a String");
theString.Should().NotBe("This is another String");
theString.Should().BeEquivalentTo("THIS IS A STRING");
theString.Should().EndWith("a String");
theString.Should().EndWithEquivalent("a string");
theString.Should().Contain("is a");
theString.Should().NotContain("is a");
theString.Should().ContainEquivalentOf("WE DONT CARE ABOUT THE CASING");
theString.Should().NotContainEquivalentOf("HeRe ThE CaSiNg Is IgNoReD As WeLl");
theString.Should().StartWith("This");
theString.Should().StartWithEquivalent("this");

There's not much to add, but for the fact that again, you'll get a bit more info when tests fail:

Image 12

Extra credit:

You can run the different tests in different ways.

Test Explorer:

The default one would be using the built in Test Runner that comes with visual studio. Just go to Test → Run→ All Tests (or hit CTRL+R,A), and it'll pop up (by default, tabbed to the left of the VS window). It looks like this:

Image 13

Resharper Unit Test:

If you happen to have resharper installed, you can go to Resharper → Unit Tests → Run Unit Tests (or CTRL+U,R by default). This will bring up resharper unit test, which I find to be a bit better, since it gives you more details and options. Here's a screen shot:

Image 14

NUnit GUI for 2.6.x:

You can download the NUnit GUI and run it as a stand alone application. Please note that currently this is not currently supported for NUnit 3.x as per the note on top. You can follow this thread if you want to know more. For now, it's only a viable option if you're using NUnit 2.6.x.

This has some pluses and some minuses.

Pluses:

  • No need to have the VS open and running if you want to test your method
  • Quick
  • Lots of options to fiddle with

Minuses:

  • Need to run a second program
  • Switching to it might be annoying (depends on what you're used to)
  • If you've never worked with it, or read my article, you might wonder how the hell it works.

Having said that, once you run the external application, the simplest way to get started is to simply drag and drop your NUnit test dll into it (remember that the unit test is really a dll project, and if you'll go into the project's folder, under the bin folder (either under debug or release, depending on what you've built), you'll find the project_name.dll that I'm talking about. Another option is to go through the GUI "Open project" and just browse to that location.

Once you've done it, F5 is the default to run all the tests, F6 to run only selected tests and F7 to run only the failed tests.

Here's the mandatory screenshot :

Image 15

The only thing to keep in mind, is that you can't use this option to run MS Tests , only NUnit tests (make sense if you think about it :)

Wrap up

We've seen 3 different ways of achieving testing for our code:

  1. MS Tests: Come with Visual Studio. Some love them, some hate them.
  2. NUnit Tests: You'll have to install the NuGet package, and then you can run them either with the VS adapter, or with an external program.
  3. Fluent Assertions: BDD syntax for sentence like assertions (In either MS tests or NUnit).

If you're not testing your code, it's as good as not being written (which in some cases is a good thing, but we would hate it if anyone will say that about our code, right?).

Testing your code gives you the freedom to change it months later, without the fear of wondering what and if will the changes break, because if something breaks, you'll know exactly what where and why broke.

This, in addition to good comments and a good versions control system should save you time and grief in the future.

If you've found this article helpful, please vote for the article, leave a message, and feel free to post back to this article Smile | :)

History

  • 13 April,       2016: Updated the article for NUnit 3 as well.
  • 30 October, 2014: Added runners, fast links to sections and screenshots.
  • 11 June,       2014: Initial release.

 

* According to legend, when a pupil demanded to know what he would gain by proving a theorem, Euclid ordered a slave to give him a coin “since he must make a gain out of what he learns.”

** Behavior-driven development

License

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