Example of Unit-test creating in Microsoft Visual Studio – C++

Example of Unit-test creating in Microsoft Visual Studio – C++

This topic describes a step-by-step process of creating the simplest unit test in Microsoft Visual Studio 2010 (C++) for a CLR Console Application. Using this example, you can learn to create your own Unit-tests. The example also demonstrates the use of the Assert class for testing the work functions.


Contents


The task

For a CLR Console Application, develop a Unit-test that tests the Max3() function, which defines the maximum element of three numbers. For the Max3() function, set the TestMax() test method. Check the function.

 

Instructions

1. Create a CLR Console Application

After starting Microsoft Visual Studio, you must select

File->New Project...

As a result, the New Project window opens (Figure 1), in which you need to select template

Visual C++ -> CLR Console Application

Project name set as MaxApp (or, if desired, another). In our case, the project folder is set to “E:\Test\” (the “Location:” field).

Figure 1. Creating an application using the CLR Console Application template

After selecting OK, an application of the CLR Console Application type will be created.

After creating the application, the Microsoft Visual Studio text box will have an approximate view, as shown in Figure 2.

Figure 2. Application view after creating

As you can see in Figure 2, the MyApp.cpp module contains the connection of the module “stdafx.h” and the main() function, which is the entry point to the program (this function is associated with the C++ program).

 

2. Implementation of function Max()

Before the declaration of the main() function, the text of the Max() function is entered, which looks like this:

// function that calculates maximum value between three integers
int Max(int a, int b, int c)
{
    int max = a;
    if (max<b) max = b;
    if (max<c) max = c;
    return max;
}

This function will need to be tested using Unit-test in Microsoft Visual Studio.

 

3. The text of the program, which must be tested

At the moment, the text of the program you want to test is as follows:

// UnitTestApp01.cpp : Defines the entry point for the console application.
// MaxApp.cpp : main project file.
#include "stdafx.h"
using namespace System;

// function that finds the maximum value between three integers
int Max(int a, int b, int c)
{
    int max = a;
    if (max<b) max = b;
    if (max<c) max = c;
    return max;
}

int main(array<System::String ^> ^args)
{
    Console::WriteLine(L"Unit-test in MS Visual Studio.");
    return 0;
}

Because this program will be tested from another testing module, then nothing needs to be entered in the main() function. Since, according to the condition of the task, you need to test the operation of the Max() function. But this will already be done from the testing module. At the moment our program is ready for testing.

 

4. Creating a test

The test is created by a separate project in the Solution. The program, which will be tested does not know about it. The test program that will test calls the functions of the program under test. In our case, the test program will call the function

int Max(int, int, int);

 

4.1. Adding a new project to the solution

To create a test, you need to create a new project in the Solution. To do this, a sequence of commands is called in Visual Studio

File -> Add -> New Project ...

This will open the “Add New Project” window, shown in Figure 3.

Figure 3. The “Add New Project” window

In the window a templates group of Visual C ++ – Test is selected. From the proposed templates, the project template “Test Project” is selected. The “Name” field indicates the name of the project that will test our program. You need to set, for example, TestMaxApp. The project is located in a separate folder “E:\Test\MaxApp”. After selecting OK, the system creates new project files that will be tested, as shown in Figure 4. A file (module) is created with the name “UnitTest1.cpp”. In this file, you need to enter the code that will test the Max() function from the MaxApp.cpp module.

Figure 4. The text of UnitTest1.cpp file. The Solution Explorer window with the displayed projects TestMaxApp and MaxApp

 

4.2. The structure of solution

As you can see in Figure 4, Solution Explorer displays the Solution Items structure, which contains two projects:

  • the MaxApp project. This is a project created using the CLR Console Application template with the Max() function, which to be tested;
  • the TestMaxApp project. This project is designed to test the functions of the MaxApp project. The program code that will test the Max() function will be added to the project file UnitTest1 of the TestMaxApp project.

Both projects can be executed independently of each other.

 

4.3. The text of the test file “UnitTest1.cpp”. Attributes [TestMethod] and [TestClass]

In the TestMaxApp project, the UnitTest1.cpp test file is the main test file. This file contains methods that will test the functions of the project “MaxApp.cpp”. The TestMaxApp project can contain any number of files that contain tests (for example, UnitTest2.cpp, UnitTest3.cpp, etc.).

Listing of the UnitTest1.cpp file generated by MS Visual Studio is as follows:

#include "stdafx.h"
using namespace System;
using namespace System::Text;
using namespace System::Collections::Generic;
using namespace Microsoft::VisualStudio::TestTools::UnitTesting;

namespace TestMaxApp
{
    [TestClass]
    public ref class UnitTest1
    {
        private:
        TestContext^ testContextInstance;

        public:
        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>

        property Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ TestContext
        {
            Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ get()
            {
                return testContextInstance;
            }

            System::Void set(Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ value)
            {
                testContextInstance = value;
            }
        };

        #pragma region Additional test attributes
        //
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //static void MyClassInitialize(TestContext^ testContext) {};
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //static void MyClassCleanup() {};
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //void MyTestInitialize() {};
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //void MyTestCleanup() {};
        //
        #pragma endregion

        [TestMethod]
        void TestMethod1()
        {
            //
            // TODO: Add test logic here
            //
        };
    };
}

As you can see from the above code, the file contains a class named UnitTest1. The class has a public method named TestMethod1().Before implementation of TestMethod1() method, the [TestMethod] attribute is placed. This means that in the body of the method, you need to enter code that will test the functions of the MaxApp project.

In the class, you can enter any number of methods that will test different functions from different modules. The main thing is that these methods are marked with the attribute [TestMethod]. For example, if you want to add a second test method named MySecondTestMethod(), you need to enter approximately the following code into the class body:

...

[Test Method]
void MySecondTestMethod()
{
    // the testing method code MySecondTestMethod()
    // ...
}

...

Similarly, the [TestClass] attribute is placed before the UnitTest1 class. This means that there are testing methods in the class.

 

4.4. Making changes in the text of UnitTest1

You can change the method names and add new methods that are marked with the [TestMethod] attribute in the UnitTest1.cpp module. With this in mind, in the UnitTest1.cpp text, the TestMethod1() method must be renamed to TestMax().

After the changes have been made, the abbreviated text of UnitTest1.cpp file module will look like:

#include "stdafx.h"
using namespace System;
using namespace System::Text;
using namespace System::Collections::Generic;
using namespace Microsoft::VisualStudio::TestTools::UnitTesting;

namespace TestProjectApp01
{
    [TestClass]
    public ref class UnitTest1
    {
        private:
        TestContext^ testContextInstance;

        public:

        ...

        [TestMethod]
        void TestMax()
        {
            //
            // TODO: Add test logic here
            //
        };
    };
}

 

4.5. Connection of the “MaxApp.cpp” module of the MaxApp project to the TestMaxApp project

To access the Max() function of the “MaxApp.cpp” module of the MaxApp project from the TestMaxApp project, you need to call this module using the #include directive.

There are 2 methods of this connection:

  • connect the file “MaxApp.cpp”, specifying its full name on the disk (or on another source);
  • in the references to the Microsoft Visual Studio assemblies, configure the folder with the MaxApp project so that it is automatically connected.

After this, you can access the “MaxApp.cpp” file by its abbreviated name. In this topic, both methods are described.

 

4.5.1. Method 1. Connection with a full name request

This method is more simplified. It is convenient when you need to connect a small number of files to the project for testing.

In the TestMaxApp project, in the “UnitTest1.cpp” file, after connecting namespaces, you need to set the following line:

#include "E:\\Test\\MaxApp\\MaxApp\\MaxApp.cpp"

This specifies the full name of the MaxApp.cpp file on the disk, in which the Max() function is located, which you need to test.

 

4.5.2. Method 2. Connection with an abbreviated name

This method is effective when you need to test several modules of different projects. A whole directory (folder) is connected with the files of the tested project. In our case, it is needed to use the folder:

E:\Test\MaxApp\MaxApp\

in the list of references to assemblies (projects) that automatically connect to the TestMaxApp project. After that, you can connect the MaxApp.cpp module by abbreviated name

#include "MaxApp.cpp"

avoiding the use of a long name as shown in section 4.5.1.

First of all, the “References …” command is called from the TestMaxApp context menu as shown in Figure 5. Another way to call – the command Project-> References … (previously need to be select TestMaxApp project).

Figure 5. Calling the default references viewer window for assemblies that are used in the TestMaxApp project

This opens the “TestMaxApp Property Pages” window which is shown in Figure 6.

Figure 6. The “TestMaxApp Property Pages” window, command “Add New Reference …”

In the “TestMaxApp Property Pages” window, you first need to activate the “Common Properties” -> “Framework and References” tab.

Then you need to select the command “Add New Reference …”. This command allows adding new folders with modules to the project, methods (functions, resources) of which can then be included in the project by the #include directive. After selecting the command, the Add Reference window, shown in Figure 7, opens.

Figure 7. The “Add Reference” window with the displayed projects in the current solution

In the “Add Reference” window, the Project tab displays the project folders that are used in this solution. In our case, only one MaxApp project is displayed, which is located in the folder

E:\Test\MaxApp\MaxApp

After selecting OK, you return to the previous window, in which the reference to the MaxApp project will be displayed in the list of references to the assemblies.

Figure 8. The “TestMaxApp Property Pages” window after adding the MaxApp project to the list of public assemblies

That’s not all! The next step is to connect the MaxTest project folder to the “Include Directories” list.

To do this, you must first activate the line

Configuration Properties -> VC++ Directories

as shown in Figure 9.

Figure 9. The “TestMaxApp Property Pages” window, line “Include Directories”

In the “General” list, “Include Directories” is selected. As a result, a dropdown list is opened, in which you need to select the command “<Edit …>”. After that, the “Include Directories” window shown in Figure 10 opens.

Figure 10. The “New Line” command and the folder selection button with the files that connect

In the “Include Directories” window, add a new line with the “New Line” command and select the folder with the MaxApp project, as shown in Figure 10. After selecting the “…” button, the standard Windows window opens to select the desired folder. In our case, you need to select a folder

E:\Test\MaxApp\MaxApp

After selecting, the Include Directories window will have the appearance as shown in Figure 11.

Figure 11. The Include Directories window after selecting the folder E:\Test\MaxApp\MaxApp

To go to the previous window, select OK.

Figure 12. The TextMaxApp Property Pages window after configuring the line “Include Directories”

To proceed to writing the program test code, select OK.

After the performed actions, all files from the folder

E:\Test\MaxApp\MaxApp

can be connected by abbreviated name, for example:

#include "MaxApp.cpp"

 

4.6. Writing code in the TestMax() method

The code that tests the Max() function fits into the body of the TestMax() method of the “UnitTest1.cpp” module. The code fragment of the TestMax() method looks like this:

...

[TestMethod]
void TestMax()
{
    //
    // TODO: Add test logic here
    //
    int t;
    t = Max(5, 6, 7);
    Microsoft::VisualStudio::TestTools::UnitTesting::Assert::AreEqual(t, 6);
};

...

The above code calls the function AreEqual() from the Assert class. This function compares the value that was returned from the Max() function and the value 6. In this case, the number 7 (maximum) is compared with the number 6. For this way, the test will not be passed, since 7 is not equal to 6. As a result, the Assert::AreEqual() function throws an exception, which will be displayed in a special window (see paragraph 5).

 

5. Running the test and checking the test results

In Microsoft Visual Studio, a special menu of commands, called Test, is implemented to work with Unit-tests. To run the test, you must select one of the commands

Test -> Run -> Tests in Current Context

or

Test -> Run -> All Tests in Solution

as shown in Figure 13.

Figure 13. Calling the test command and viewing the result

After starting the test, the result can be viewed at the bottom of the “Test Results” window. As you can see, the test is failed. This is logical, because in the function Assert::AreEqual() we compare the numbers 6 and 7, which are different from each other. Here the number 6 is specially introduced instead of the number 7.

If instead of 6 you enter the correct answer – the number 7 (maximum between 5, 6, 7), then the test will be passed. In this case, the text of the TestMax() method will be as follows:

...

[TestMethod]
void TestMax()
{
    //
    // TODO: Add test logic here
    //
    int t;
    t = Max(5, 6, 7);
    Microsoft::VisualStudio::TestTools::UnitTesting::Assert::AreEqual(t, 7);
};

...

The result window is shown in Figure 14.

Figure 14. The test result for the case if you enter the correct checking

Now we can conclude that the function Max() was developed correctly.

 

6. The code of UnitTest1 module

Below is the text of UnitTest1.cpp, which tests the Max() function from the module “MaxApp.cpp”:

#include "stdafx.h"
using namespace System;
using namespace System::Text;
using namespace System::Collections::Generic;
using namespace Microsoft::VisualStudio::TestTools::UnitTesting;

// method 1 - specifying the full name
// #include "E:\\Test\\MaxApp\\MaxApp\\MaxApp.cpp"

// method 2 - MaxApp connection by short name
#include "MaxApp.cpp"

namespace TestMaxApp
{
    [TestClass]
    public ref class UnitTest1
    {
        private:
        TestContext^ testContextInstance;

        public:
        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>

        property Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ TestContext
        {
            Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ get()
            {
                return testContextInstance;
            }

            System::Void set(Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ value)
            {
                testContextInstance = value;
            }
        };

        #pragma region Additional test attributes
        //
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //static void MyClassInitialize(TestContext^ testContext) {};
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //static void MyClassCleanup() {};
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //void MyTestInitialize() {};
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //void MyTestCleanup() {};
        //
        #pragma endregion

        [TestMethod]
        void TestMax()
        {
            //
            // TODO: Add test logic here
            //
            int t;
            t = Max(5, 6, 7);
             Microsoft::VisualStudio::TestTools::UnitTesting::Assert::AreEqual(t, 7);
        };
    };
}

 

7. Conclusion. Interaction between projects

In this topic, two projects are developed in the solution. One MaxApp project contains the Max() function to be tested. The second project TestMaxApp contains methods that test.

In Microsoft Visual Studio, each project is run using various menu commands. For example, the MaxApp project is launched in the standard way from the Run menu. And the test project TestMaxApp is run from the special menu “Test”.

 


Related topics