Thursday, December 06, 2012

Unit test for unmanaged C++ in Visual Studio


Bugs free software is a dream of every person who involve in software development process. But with the today complex software systems and even more featured requirements , it is quite a challenge to overcome this specific expectation.
There are number of methodologies and tools for bug tracking, debugging, error tracing and various level to testing. But as the developers unit testing and integrated testing are the most important kind of testing that require to implement a bug free software. So in this article I'm  going to show you some tips and methodologies of unit testing.   As C++ developers knows unit testing for unmanaged C++ is a quit cumbersome and there is no standers way to do the unit testing for development environment. Normally expert developers prefers the TDD (Test driven development) for error less software and as a confident development method  that support to maintain and extend the already developed software.

Most of the Unmanaged C++ developers  developers mostly use some kind of third party Unit Test frame-works such as 'Boost Test', 'Google Test' or 'cppUnit'  even they works on windows environment. Actually these unit testing frameworks have some unique features and capabilities than .NET unit testing framework, such as object mocking and various Assert rules. But when you are working with Visual Studio IDE, using .NET unit testing framework may easy to use and compatible than other unit testing frameworks. But even some developers uses .NET unit testing capability for MFC or ATL projects (Manage C++), Most of them  don't have idea how to use it with unmanaged C++ development. But If  you are involving in DLL or LIB development using C++ it is easy to do unit testing by adding the static or dynamic library as reference to the testing project.

But in this article I'm going to introduce you how the set-up unit testing for  for Win32 console application  (Unmanaged C++) (But even this is possible with Win32 windows applications) in Visual Studio 2010 with Windows operation system. Even I describing this for Visual Studio 2010, It may applicable with other versions such as 2012,2008 or 2005. So lets start as step by step guide from here.

Today I'm going to develop a simple calculator with unit testing for the functionality.

Add Main Project

1. Open visual studio 2010 and Create a new project by using 'File' -> 'New'
2. In new project window go to right hand side panel -> select Visual C++ -> select Win32
3. In the Right hand side panel select 'Win32 Console Application'
4. Type 'calculator' in Name text field bellow and select the location as you need.


5. Then next window (Win32 Application Wizard) just click next
6. Then next window select 'Empty Project' and keep setting as this image. then click finish



So this is our main project and main method should be in this project for initiate the application.

7. In the Solution explorer expand calculator -> right click on 'Source File' -> 'Add' -> 'New Item' -> select 'C++ File (.cpp)'
8. Type the name 'main' in Name text box and click add


Add Lib Project

1. Right click Solution in 'Solution explorer' and select 'Add' -> 'New Project'
2. Next window in left pane select Win32 and in right pane select 'Win 32 Console Application'
3. Type 'calculator_lib' in Name text box and click ok.
4. In next window just click next
5. In next window select Static library and keep other setting as image. Then click finish.




Add Test Project

1. Same as above right click Solution in 'Solution explorer' and select 'Add' -> 'New Project'
2. Next window left hand panel select 'Visual C++'->'Test'
3. Type calculator_test in Name text box
4. Click OK

Now your solution explorer should have three project and It should looks like this image


Configurations Test Project 

1. Right click calculator_test project and select properties'
2. In left hand panel select 'Common Properties' -> 'Framework and Referance'
3. In right side panel click 'Add New Reference' button at bottom
4. Select 'Project' tab then select  'calculator_lib' and  click OK
5. Left side panel select 'Configuration Properties' then 'General'
6. In top left combo box select 'All Configurations
7. Change the Target Name from 'DefaultTest' to 'CalculatorTest'
8. Then expand 'C/C++' and select 'Genaral' in left hand panel
9. In right hand panel there is a entry 'Additional Include Directories' paste the bellow text there

$(SolutionDir)\calculator_lib;%(AdditionalIncludeDirectories)

10. change 'Common Language Run Time Support' as 'Common Language RunTime Support (/clr)' in Right side panel and click OK

Configurations Main Project 

1. Right click on calculator project and select properties.
2. In top left combo box select 'All Configurations
3. In left hand panel select 'Common Properties' -> 'Framework and Referance'
4. In right side panel click 'Add New Reference' button at bottom
5. Select 'Project' tab then select  'calculator_lib' and  click OK
6. Then expand 'C/C++' and select 'Genaral' in left hand panel
7. In right hand panel there is a entry 'Additional Include Directories' paste the bellow text there

$(SolutionDir)\calculator_lib;%(AdditionalIncludeDirectories)

8. Click OK


C++ Coding

1. Go to solution explorer and expand the calculator project
2. open the 'main.cpp' file and paste the following code on it.

#include <iostream>
using namespace std;
int main()
{
 cout << "This is my first Unit Test for unmanaged C++ application";
 return 0;
}
3. Click Ctl+F7 to build the solution and solution should build with three projects as bellow image.



4. Right click the 'calculator_lib' project in solution explorer and click 'Add'-> 'Class'
5. Select 'C++ Class' from right panel in next window and click add.
6. In next window add 'basic_calculator' in 'Class name' text box and click finish.


7. Open' basic_calculator.h' file and replace the following code in to it
#pragma once
class basic_calculator
{
public:
 basic_calculator(void);
 ~basic_calculator(void);
 int add(int a,int b);
 int minus(int a,int b);
 int multiply(int a,int b);
 int devid(int a,int b);
};

8. Open 'basic_calculator.cpp' file and replace the fallowing code in to it


#include "StdAfx.h"
#include "basic_calculator.h"
basic_calculator::basic_calculator(void)
{
}
basic_calculator::~basic_calculator(void)
{
}
int basic_calculator::add(int a,int b)
{
 return a+b;
}
int basic_calculator::minus(int a,int b)
{
 return a-b;
}
int basic_calculator::multiply(int a,int b)
{
 return a*b;
}
int basic_calculator::devid(int a,int b)
{
 return a/b;
}

Adding test case
1. Right click the calculator_test project and click 'Add' then 'New Test'
2. In next window select 'UnitTest' and add 'basic_calculator_test' for 'Test Name' text field and click OK


3. Open basic_calculator_test.cpp file and clear unawareness comment, include 'basic_calculator.h' file and create a pointer 'by basic_calculator' class

Note: Actually here I'm showing how to write vary basic few test cases for your start. Later you can find your own journey in unmanaged C++ unit testing.


4. Change test method name to addTest and write a test case for 'add' functionality using assert
5. Same as this add another three test cases for remaining functionality also.
6. So finally your  'basic_calculator_test' should be like this

Note: Mostly IntelliSense not supporting for C++ Test project in Visual Studio 2010

#include "stdafx.h"
#include "basic_calculator.h"

using namespace System;
using namespace System::Text;
using namespace System::Collections::Generic;
using namespace Microsoft::VisualStudio::TestTools::UnitTesting;


namespace calculator_test
{

[TestClass]
public ref class basic_calculator_test
{
private:
TestContext^ testContextInstance;
basic_calculator* test_calculator;

public:
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;
 }
};

[TestMethod]
void addTest(){Assert::AreEqual<int>(6, test_calculator->add(4,2));};

[TestMethod]
void minusTest(){Assert::AreEqual<int>(2, test_calculator->minus(4,2));};

[TestMethod]
void multiplyTest(){Assert::AreEqual<int>(8, test_calculator->multiply(4,2));};

[TestMethod]
void devidTest(){Assert::AreEqual<int>(2, test_calculator->devid(4,2));};

[TestMethod]
void addTestForFail(){Assert::AreEqual<int>(5, test_calculator->add(3,3));};
};
}

7. Now you finish creating test cases for your basic_calculator.
8. Right click on "Soloution 'calculator'" in project explorer and click properties
9. Next window select calculator_test as 'Single startup project' and click ok


10. Then press Ctl+F7 to build the project and then F5 to run.
11. You will see your Unit test are running in the bottom and you can see the result in 'Test Result' Window

12. So as we expected four of our unit test passed and one failed you can write more advance test cases by improving your knowledge and  reading about Assert functions.

Building Application
1. Open main file under 'calculator' project and replace with fallowing code.


#include <iostream>
#include "basic_calculator.h"

using namespace std;

int main()
{
cout << "This is my first Unit Test for unmanaged C++ application" << endl;

basic_calculator* my_calculator = new basic_calculator();
cout << "4 + 2 =" << my_calculator->add(4,2) << endl;
cout << "4 - 2 =" << my_calculator->minus(4,2) << endl;
cout << "4 * 2 =" << my_calculator->multiply(4,2) << endl;
cout << "4 / 2 =" << my_calculator->devid(4,2) << endl;

system("pause");
return 0;

}

2.Right click on "Soloution 'calculator'" in project explorer and click properties again
3. Next window select 'calculator' as 'Single startup project' and click ok
4. Build the project and run then you can see the result


Congratulations!  Now you know how to create unit test for unmanaged C++ applications. So need to do more studies to be a expert Unit test writer. I'm putting her some resource for your referance

http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.assert.aspx
http://msdn.microsoft.com/en-us/library/te3ecsc8.aspx

8 comments:

  1. Very helpful tutorial. Thanks!

    ReplyDelete
  2. Thanks for great tutorial, really helpfull. You made my day better.
    Thanks!

    ReplyDelete
  3. How to create a unit test for MFC DLL? I am running into errors using any framework like WinUnit, CppUnitTestFramework etc.

    ReplyDelete
  4. This tutorial has been great for me. I wasn't sure what c++ unit testing was. My office talks about it frequently.

    ReplyDelete
  5. Best example. I owe you a drink.

    ReplyDelete
  6. Спасибо, чувак!

    ReplyDelete
  7. Hi,

    No doubt this is a excellent tutorial. It saved a lot of time for me.
    But my concern is: In the basic_calculator_test.cpp we are adding the tests for the class member function manually.

    Is there any way to add all the member function automatically in test file.

    Thanks

    ReplyDelete