Note: this article is published on 07/11/2024.

This series of articles will discuss Unit Test

This article will discuss the basic of Unit Test.

A - Introduction

Unit tests give developers and testers a quick way to look for logic errors in the methods of classes. The content of this article:

Unit testing is a software testing method by which individual units of source code—sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures—are tested to determine whether they are fit for use.

Image, when we have a developed software, QA spent months to test it throughly, while in the last stage, we find a new bug, it is a very simple fix, however, to make sure the software working well in the whole, we need to test it piece by piece, so called regression testing. If let QA to retake the job, that will take one testing cycle, months work. However, if we have s unit test for all individual piece of software, especially, if the tests can be run automatically, then we can reduce the time for the regression testing. This is what the unit test for.

  • A - Introduction
  • B - AAA in Unit Test
  • C - Testing tools
  • D - A Sample of MS Unit Test
  • E - Why Unit Test
  • F - Characteristics of a good unit test

B - AAA in Unit Test

The AAA (Arrange, Act, Assert) pattern is a common way of writing unit tests for a method under test.

  • The Arrange section of a unit test method initializes objects and sets the value of the data that is passed to the method under test.

  • The Act section invokes the method under test with the arranged parameters.

  • The Assert section verifies that the action of the method under test behaves as expected. For .NET, methods in the Assert class are often used for verification.Unit test tools and tasks --- MS

The unit tests are created

C - Testing tools

.NET is a multi-language development platform, for each language, one can choose between several test frameworks.

C -1: NUnit

NUnit is a unit-testing framework for all .NET languages. Initially, NUnit was ported from JUnit (born on 1997 on a flight by Kent Beck, Erich Gamma), and the current production release has been rewritten with many new features and support for a wide range of .NET platforms. It's a project of the .NET Foundation.

Major atributes:

  • [TestFixture] --- a class that contains unit tests.
  • [Test] --- a method is a test method.

C -2: xUnit

xUnit is a free, open-source, community-focused unit testing tool for .NET. The original inventor of NUnit v2 wrote xUnit.net. xUnit.net is the latest technology for unit testing .NET apps. xUnit.net is a project of the .NET Foundation and operates under its code of conduct.

Major atributes:

  • none --- a class that contains unit tests.
  • [Fact] --- a method is a test method.

C - 3: MSTest

MSTest is the default test framework that is shipped along with Visual Studio. It is the Microsoft test framework for all .NET languages. It's extensible and works with both .NET CLI and Visual Studio.

Major atributes:

  • [Testclass] --- a class that contains unit tests.
  • [TestMethod] --- a method is a test method.

D - A Sample of MS Unit Test

We have a BankAccount class:

using System;

namespace BankAccountNS
{
    /// <summary>
    /// Bank account demo class.
    /// </summary>
    public class BankAccount
    {
        private readonly string m_customerName;
        private double m_balance;
        private BankAccount() { }
        public BankAccount(string customerName, double balance)
        {
            m_customerName = customerName;
            m_balance = balance;
        }
        public string CustomerName
        {
            get { return m_customerName; }
        }
        public double Balance
        {
            get { return m_balance; }
        }
        public void Debit(double amount)
        {
            if (amount > m_balance)
            {
                throw new ArgumentOutOfRangeException("amount");
            }
            if (amount < 0)
            {
                throw new ArgumentOutOfRangeException("amount");
            }
            //m_balance += amount; // intentionally incorrect code
            m_balance -= amount;
        }
        public void Credit(double amount)
        {
            if (amount < 0)
            {
                throw new ArgumentOutOfRangeException("amount");
            }
            m_balance += amount;
        }
        public static void Main()
        {
            BankAccount ba = new BankAccount("Mr. Bryan Walton", 11.99);
            ba.Credit(5.77);
            ba.Debit(11.22);
            Console.WriteLine("Current balance is ${0}", ba.Balance);
        }
    }
}

Create a unit test project (we use Visual Studio 19)

  1. On the File menu, select Add > New Project.

  2. Type test in the search box, select C# as the language, and then select the C# MSTest Unit Test Project (.NET Core) for .NET Core template, and then click Next.

  3. Name the project BankTests and click Next.

  4. Choose a recommended target framework (I used .Net Core 3.1), and then choose Create.

    The BankTests project is added to the Bank solution. Change the program.cs file name to BankAccountTests.cs.

  5. In the BankTests project, add a reference to the Bank project.

    In Solution Explorer, select Dependencies under the BankTests project and then choose Add Reference (or Add Project Reference) from the right-click menu.

  6. In the Reference Manager dialog box, expand Projects, select Solution, and then check the Bank item.

  7. Choose OK.

We have the solution like this

Copying the code below into the BankAccountTests.cs:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using BankAccountNS;

namespace BankTest
{
    [TestClass]
    public class BankAccountTests
    {
        [TestMethod]
        public void Debit_WithValidAmount_UpdatesBalance()
        {
            // Arrange
            double beginningBalance = 11.99;
            double debitAmount = 4.55;
            double expected = 7.44;
            BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);
            // Act
            account.Debit(debitAmount);
            // Assert
            double actual = account.Balance;
            Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly");
        }
    }
}

Test class requirements

The minimum requirements for a test class are:

  • The attribute is required on any class that contains unit test methods that you want to run in Test Explorer.

  • Each test method that you want Test Explorer to recognize must have the attribute.

You can have other classes in a unit test project that do not have the [TestClass] attribute, and you can have other methods in test classes that do not have the [TestMethod] attribute. You can call these other classes and methods from your test methods.

Test method requirements

A test method must meet the following requirements:

  • It's decorated with the [TestMethod] attribute.

  • It returns void.

  • It cannot have parameters.

Build and run the test:

  • Build Solution.

  • Open the Test Explorer by choosing Test > Test Explorer from the top menu bar (or press Ctrl + E, T).

We have Test Explorer:

  • Choose Run All to run the test (or press Ctrl + R, V).

When something is wrong, the Test Explorer could show more messages like this:

The Test Explorer toolbar helps you discover, organize, and run the tests that you are interested in.

E - Why Unit Test

F - Characteristics of a good unit test

References