Native Unit Tests using Visual Studio 2012






4.45/5 (8 votes)
Using the native unit test project in Visual Studio 2012.
Introduction
Native C++ test unit frameworks are a lot, but In visual studio 2012 there is a fantastic project template called Native Unit Test and it's fully supported in the visual studio to run the tests in the test explorer.
Background
I searched for testing frameworks for native C++, as many experienced programmers said Google Test Framework or known as GTest is the best, I used it is more advanced but it shows the result in a dos window coloring the alerts.., but in this visual studio test project it is different we will use the visual studio to write and run our tests
Using the code
We will create a solution that contains three projects.
- The first is a Win32 library called DemoBusiness that will contain our business classes.
In this library I'll use the class that visual studio generated for me
CDemoBusiness
. - The second project is the native unit test project to test the previous business project. Create it from File -> New -> Project -> c++ -> Test -> Native Unit Test.
- The optional main application that will uses the business classes// in our case it is optional as we are discovering the native testing feature in VS2012.
- *After adding any new logic to the DemoBusiness project go to the test and add your test method
- *After any changes in the DemoBusiness build it then build the test module and run all the tests from the test explorer
- *All the
Logger::WriteMessage(L"")
the notes will appear in the output window but select Tests in show output from.
// DemoBusiness.h
#ifdef DEMOBUSINESS_EXPORTS
#define DEMOBUSINESS_API __declspec(dllexport)
#else
#define DEMOBUSINESS_API __declspec(dllimport)
#endif
class CDemoBusinessTest;
// This class is exported from the DemoBusiness.dll
class DEMOBUSINESS_API CDemoBusiness
{
private://private members
int data;
public:
CDemoBusiness(void);
// TODO: add your methods here.
template<class T> T Max(T item1, T item2) const
{
if (item2 > item1)
{
return item2;
}
return item1;
}
void SetData(int data);
int GetData() const;
int BadAdd(int num1, int num2) const;
int ThrowingException() const;
const int* ReturnNullData() const;
const int* ReturnData() const;
friend class CDemoBusinessTest;
};
// DemoBusiness.cpp
#include "stdafx.h"
#include "DemoBusiness.h"
CDemoBusiness::CDemoBusiness() : data(0)
{
return;
}
void CDemoBusiness::SetData( int data )
{
this->data = data;
}
int CDemoBusiness::GetData() const
{
return this->data;
}
int CDemoBusiness::BadAdd( int num1, int num2 ) const
{
return num1 + num2 + 10;
}
int CDemoBusiness::ThrowingException() const
{
throw exception("Problem");
return 0;
}
const int* CDemoBusiness::ReturnNullData() const
{
return nullptr;
}
const int* CDemoBusiness::ReturnData() const
{
return &data;
}
Add the dependency to the DemoBusiness project. add the output DemoBusiness.lib to the linker input and add its output directory to the libraries directory in C++ directories, make sure they have the same output directory if it is shared linking not static linking, it is recommended to use static linking.
Delete the default unittest1.cpp file and add a new cpp file for the test, I have created the following test for our class:
#include "stdafx.h"
#include "../DemoBusiness/DemoBusiness.h"//this is the file containing the code to test
#include <CppUnitTest.h>
#include <exception>
using namespace std;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
// the following attributes are optional just attributes for more details about the test module
// mention this attributes once per any test module(test project)
BEGIN_TEST_MODULE_ATTRIBUTE()
TEST_MODULE_ATTRIBUTE(L"Project", L"DemoBusiness")
TEST_MODULE_ATTRIBUTE(L"Owner", L"Ahmed")
TEST_MODULE_ATTRIBUTE(L"Date", L"22/10/2013")
END_TEST_MODULE_ATTRIBUTE()
// the following method is optional also just in case of need
TEST_MODULE_INITIALIZE(ModuleStartup)
{
Logger::WriteMessage(L"The test is starting....");
///////////////////////////////////////////////
// Initialize some important data //
/////////////////////////////////////////////
}
// the following method is optional also just in case of need
TEST_MODULE_CLEANUP(ModuleFinalize)
{
Logger::WriteMessage(L"Finalizing the test.");
///////////////////////////////////////////////////////////
// Finalize any previously initialized data //
/////////////////////////////////////////////////////////
}
TEST_CLASS(CDemoBusinessTest)
{
public:
CDemoBusinessTest()
{
Logger::WriteMessage(L"Inside the CDemoBusinessTest");
}
//optional info about the test class
BEGIN_TEST_CLASS_ATTRIBUTE()
TEST_CLASS_ATTRIBUTE(L"Owner", L"Ahmed")
TEST_CLASS_ATTRIBUTE(L"Descrioption", L"CDemoBusiness")
TEST_CLASS_ATTRIBUTE(L"Priority", L"Critical")
END_TEST_CLASS_ATTRIBUTE()
// optional initialization method if needed
TEST_CLASS_INITIALIZE(ClassInitialize)
{
Logger::WriteMessage(L"Initializing the class");
}
//optional finalization method if needed
TEST_CLASS_CLEANUP(ClassFinalize)
{
Logger::WriteMessage(L"Finalizing the class");
}
BEGIN_TEST_METHOD_ATTRIBUTE(TestInitialData)
TEST_OWNER(L"Ahmed")
TEST_DESCRIPTION(L"Make sure that data is initialized to zero,
as data is private this testclass must be friend to our class")
END_TEST_METHOD_ATTRIBUTE()
TEST_METHOD(TestInitialData)
{
CDemoBusiness demo;
Assert::AreEqual(demo.data, 1);
//make sure that they are equal if not the test fails
}
TEST_METHOD(TestMax)
{
CDemoBusiness demo;
double d1 = 192.123;
double d2 = 192.122;
Assert::AreEqual(demo.Max(d1, d2), d1);
}
TEST_METHOD(TestDataTransfer)
{
CDemoBusiness demo;
int data = 100;
demo.SetData(data);
Assert::AreEqual(demo.GetData(), data);
}
TEST_METHOD(TestBadAdd)
{
CDemoBusiness demo;
int num1 = 10;
int num2 = 20;
int addition = num1 + num2;
Assert::AreNotEqual(demo.BadAdd(num1, num2), addition);
}
TEST_METHOD(TestThrowingException)
{
CDemoBusiness demo;
Assert::ExpectException<exception>([&]
{
demo.ThrowingException();
});
}
TEST_METHOD(TestReturnNullData)
{
CDemoBusiness demo;
Assert::IsNull(demo.ReturnNullData());
}
TEST_METHOD(TestReturnData)
{
CDemoBusiness demo;
Assert::IsNotNull(demo.ReturnData());
}
TEST_METHOD(AreSameTest)
{
int x = 100;
int& y = x;
Assert::AreSame(x, y);
}
};
Points of Interest
For more information about native unit testing:
- Using Microsoft.VisualStudio.TestTools.CppUnitTestFramework: http://msdn.microsoft.com/en-us/library/hh694604.aspx
- Using Assert::ExpectException with Native Unit Testing in VS11: http://blogs.msdn.com/b/dgartner/archive/2012/04/22/using-assert-expectexception-with-native-unit-testing-in-vs11.aspx
- Running Unit Tests with Test Explorer: http://msdn.microsoft.com/en-us/library/hh270865.aspx
This is the output of the testing: