Unit Testing has been an inherent part of software
development today. In Unit Testing, individual units of software are
tested. While manual testing of individual functionality has been part of the development cycle, more recently these testing is automated with a testing framework.
Additional Reference:
Write unit tests for C/C++ in Visual Studio
Using Assert::ExpectException with Native Unit Testing in VS11
GitHub page for the code
GitHub Link for Code
In this article, I am going to illustrate the unit testing example
in C++ using Visual Studio 2017 IDE and Native Unit Test Project. For
illustration, unit test and actual software are contained within a solution. The
code is contained in the basiccpp solution which currently includes one project
and one test project and can be obtained from GitHub.
To get started, I have a solution named ‘basiccpp’ solution.
The solution currently contains a console application, basiccpp, written in C++.
Step 1: Add a test
project.
In the solution explorer, right-click to get the context
menu and click ‘Add’ and select Test. Select the test framework. In this example,
I am using ‘Native Unit Test Project’. The native unit test project resides in
namespace “Microsoft::VisualStudio::CppUnitTestFramework”.
The test project created will test the functions within the
basiccpp project. The basiccpp project is a window console application written
in C++.
Step 2: Add a reference
For the test project to get access to the basiccpp project,
I will add a reference to the project.
Right-click the ‘References’ in the test project, and click
Add Reference and in the window displayed, check the basiccpp project. If a single test project needs to test multiple projects, then I would select all
the projects I am testing.
Now the reference is added, I can start creating tests for
the projects.
Step 3: Add Test
By default, Visual Studio template provides us with a
unittest1.cpp file. I am going to rename this such that I know by looking at
the file name the behavior I am testing. In this example, I am going to test
Array.cpp file. Thus, I would name it as ‘ArrayTest.cpp’.
The specification of Array is in Array.hpp file and actual
impelementaiton is in Array.cpp file. The content of this Array.hpp file is
shown below:
#pragma once
#ifndef ARRAY_HPP_INCLUDED
#define ARRAY_HPP_INCLUDED
#endif
#include <cassert>
#include <ostream>
#include <utility>
template <typename T>
class Array {
private:
T* m_ptr{ nullptr };
int m_size{ 0 };
public:
Array()
= default;
~Array();
//Constructor to
create an array of defined size
explicit Array(int size);
//copy constructor
Array(const Array& source);
T& operator[](int index);
T operator[](int index) const;
void print() const;
int Size() const;
bool IsValidIndex(int index) const;
};
For testing, I will add test targeting publicly exposed the function of Array<T> class.
Since I am targeting functions defined in Array.hpp in
basiccpp project, I am going to include Array.cpp in the ArrayTest.cpp by
adding the following line:
#include "..\basiccpp\Array.cpp"
The Visual Studio will provide the IntelliSense as I am
typing to the referenced project and I can select the correct include
file.
Step 4: Create tests
I am going to update the content of ‘ArrayTest.cpp’. In
minimum, the structure of the test class one method with the following
structure:
namespace basicTest
{
TEST_CLASS(my_test_class)
{
public:
//test creation, size
and [] operators.
TEST_METHOD(my_test_method)
{
//TODO: add test logic here.
}
}
}
I can create as many methods within the class. The full
content of the file test class for ArrayTest is shown below:
#include "stdafx.h"
#include "CppUnitTest.h"
#include "..\basiccpp\Array.cpp"
#include <functional>
#include <assert.h>
using namespace
Microsoft::VisualStudio::CppUnitTestFramework;
namespace basicTest
{
TEST_CLASS(ArrayTest)
{
public:
//test creation, size
and [] operators.
TEST_METHOD(ArrayTest_Size)
{
int size = 5;
Array<int> mArray{ size };
for (int i = 0; i < size;
i++) {
mArray[i] = i;
}
Assert::AreEqual(size,
mArray.Size());
Assert::IsTrue(mArray[0] == 0);
Assert::IsTrue(mArray[4] == 4);
}
//test the empty
function
TEST_METHOD(ArrayTest_Empty)
{
int size = 5;
Array<int> mArray0{ 0 };
Assert::IsTrue(mArray0.IsEmpty());
Array<int> mArray{ size };
for (int i = 0; i < size;
i++) {
mArray[i] = i;
}
Assert::IsFalse(mArray.IsEmpty());
}
//test isValidIndex function
TEST_METHOD(ArrayTest_IsValidIndex)
{
int size = 5;
Array<int> mArray{ size };
Assert::AreEqual(size,
mArray.Size());
Assert::IsTrue(mArray.IsValidIndex(1));
Assert::IsFalse(mArray.IsValidIndex(5));
};
//Test the method
indexoutofbount by passing the invalid index and checking
//if the exception is
thrown
TEST_METHOD(ArrayTest_IndexoutOfBound)
{
int size = 5;
Array<int> mArray{ size };
auto func = [mArray, size]
{
mArray[size + 100]; };
Assert::ExpectException<IndexOutOfBoundsException>(func);
}
//test copy
constructor
TEST_METHOD(ArrayTest_CopyConstructor)
{
int size = 5;
Array<int> mArray{ size };
for (int i = 0; i < size;
i++) {
mArray[i] = i;
}
Array<int> cArray = mArray;
cArray[0] = 100;
Assert::IsTrue(cArray[0] != mArray[0]);
}
};
}
Step 5: Run the test using Test Explorer
Once I have written the test, I can build and run the
test using Test Explorer. In addition, by adding breakpoints to the method as
well as in the test, I can debug the test.
Write unit tests for C/C++ in Visual Studio
Using Assert::ExpectException with Native Unit Testing in VS11
GitHub page for the code
GitHub Link for Code