Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / DevOps / testing

Native Unit Tests using Visual Studio 2012

4.45/5 (8 votes)
23 Oct 2013CPOL2 min read 59.5K   544  
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.

  1. 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.
  2. C++
    // 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;
    };    
    C++
    // 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;
    }  
  3. 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.
  4. New native test project

    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:

    C++
    #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);
        }
    }; 
  5. 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::<span style="color: black; font-family: Consolas, "Courier New", Courier, mono; font-size: 9pt; white-space: pre; background-color: rgb(251, 237, 187);">WriteMessage(L"")</span> the notes will appear in the output window but select Tests in show output from.

Points of Interest

For more information about native unit testing:

  1. Using Microsoft.VisualStudio.TestTools.CppUnitTestFramework: http://msdn.microsoft.com/en-us/library/hh694604.aspx
  2. 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
  3. Running Unit Tests with Test Explorer: http://msdn.microsoft.com/en-us/library/hh270865.aspx

This is the output of the testing:

Image 2

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)