Your First Unit Test in xUnit

This is Part 3 in my series on Automated Testing. If you like to review some of the philosophical underpinnings of automated testing or would like to get an overview of some of the classification of frameworks and tools in this space, please check out those previous posts:

I’ll be using the Visual Studio IDE and the xUnit Testing Framework in this post and related posts in the future. If you don’t have a copy of Visual Studio, you can get the community edition that’s free forever (for personal use). Visual Studio can be a bit daunting at first as it is an IDE for so many different things. Take heart – there are so many resources on YouTube and other areas of the web that you can get up to speed quickly. If you need some help on how to install it, you can check out the official documentation here.

With those introductions out of the way, we are ready to write our first unit test. For this tutorial, I have a .NET 5 Console Application project in Visual Studio with a simple Greeter class which I’m citing below:

namespace UnitTestDemoPartOne
{
    public class Greeter
    {
        public string SayHello(string name)
        {
            return $"Hello, {name}";
        }
    }
}

Add a Unit-Test Project

We’ll want to separate out our production operational code from our testing code. For this reason, we’ll add a new project into our solution – a .NET (Core) Class Library project. My naming convention is to suffix the project name with “.UnitTests”.

Solution Explorer showing a new .NET Core class library project for housing unit tests

After adding the new project, link both these projects together by right-clicking on the UnitTests project, choosing “Add” > “Project Reference” and selecting the console application containing your operational code.

Add Dependencies via NuGet

Next, we’ll want to pull a few packages off of NuGet that will assist in our testing, namely the xUnit test framework, Microsoft.Net.Test.Sdk – the test host that will host our xUnit tests, xunit.runner.visualstudio runner that will link our xUnit tests, our Microsoft.Net tests and execute those tests.

NuGet package manager window showing the xUnit package along with the Microsoft test SDK and xUnit VS runner

Write Your Unit Test

If you have not already done so, add a new C# class file to your Unit Testing project. The naming convention that I like to use is to name it the same as the class I’m testing along with a suffix of “Tests”. In our example, we are testing a class named “Greeter”. As such my test class name is “GreeterTests”.

Add a using statement towards the top to reference xUnit so you can use all its goodness in this class. Write a unit test to test the “SayHello” method in the Greeter class, like I have shown below:

using Xunit;

namespace UnitTestDemoPartOne.UnitTests
{
    public class GreeterTests
    {
        [Fact]
        private void SayHello_WhenCalledWithAName_ReturnsAGreetingWithThatName()
        {
            // Arrange
            var greeter = new Greeter();

            // Act
            var result = greeter.SayHello("Tom");

            // Assert
            Assert.Equal("Hello, Tom", result);
        }
    }
}

I want to call your attention to a few things in the example above:

Name of the Test Method: In the example above you’ll see an unusually long method name – SayHello_WhenCalledWithAName_ReturnsAGreetingWithThatName. I use a three part naming convention naming my tests, separating each part with an underscore:

  • Part 1: What am I testing? I am testing the “SayHello” method.
  • Part 2: What is the scenario that I’m testing? I’m testing the scenario where I call this method with a name parameter.
  • Part 3: What is the outcome I’m expecting? I expect the method to return a greet with the name that I passed in.

Don’t worry too much if the name gets a bit lengthy. You’ll remember from the previous episodes that one of the main things that we are going for is easy readability.

Fact Attribute: You’ll notice that I’ve decorated my test method with a “Fact” attribute. This annotation lets the xUnit test framework know that this is a test as opposed to some other helper method.

Triple A Pattern: You’ll see that my test method is broken up into three parts, commonly referred to as the “Triple A” pattern. This patterns provides a bit of uniformity to tests and is a good template to follow, especially when starting out with the practice of writing tests. The three parts are:

  • Arrange: Here’s where I setup the thing that I’m testing.
  • Act: This is where I invoke the piece of code that I’m testing.
  • Assert: This is where I’ll check whether the thing that I invoked produced the results that I expected. xUnit, like pretty much all other testing frameworks provide a set of assertion constructs that let you specify your expected outcome. In my example, I’m asserting that I expect the output of the SayHello method to be “Hello, Tom!”

Run Your Unit Test

If not already open, bring up the Test Explorer window within Visual Studio.

Test Explorer menu item in Visual Studio under the Test section.

If the new test that you wrote is not already listed in the Test Explorer, build your solution so that the tooling can pick up your new test.

Test Explorer in VS displaying the test you created.

You can right-click on a single test and run it. If you have multiple tests, you can them run them as a group. You can also use the Play buttons to execute the highlighted test or all tests in your project.

If all goes well, the Test Explorer will indicate that your test has passed.

Test explorer showing that the unit test has passed.

Now, as a sanity check, introduce a “bug” within your operational code or change something in your test method so that your assertion will not be correct. For example, I changed my SayHello method to return “Hi, [name]” instead of “Hello, [name]”.

Modified SayHello method to demonstrate a failed test.

Re-run the test and confirm that your test does not pass.

Test explorer showing the failed test.

Here we see that the Test Detail Summary section is showing the test failure along with some details. It’s pointing out that we expected the method to return “Hello, Tom” when in actuality, it returned “Hi, Tom”.

Closing Remarks

Congratulations on your 1st unit test! You can also download the demo project that I referenced in this blog post, from my GitHub account, here:

tvaidyan/UnitTestsDemoPart1: Companion repo to my Your First Unit Test in xUnit blog post on tvaidyan.com (github.com)

Please feel free to clone it and play with it to get a better understanding of how things are wired up. This is clearly a very contrived example but you can probably see how having a suite of such automated tests in a real-world application can be beneficial. There is a sense of freedom that you feel being able to make a change in your codebase and having the assurance that you didn’t likely break anything by running your unit-tests and confirming that they all still pass.

Stay tuned for more posts in this series where we’ll dig deeper, writing more tests and exploring many other aspects of automated testing.

Leave a Comment

Your email address will not be published. Required fields are marked *