65.9K
CodeProject 正在变化。 阅读更多。
Home

使用Visual Studio 2012进行原生单元测试

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.45/5 (8投票s)

2013年10月23日

CPOL

2分钟阅读

viewsIcon

60175

downloadIcon

578

使用 Visual Studio 2012 中的原生单元测试项目。

引言

原生 C++ 测试单元框架有很多,但在 Visual Studio 2012 中有一个很棒的项目模板,名为 原生单元测试,它完全支持在测试资源管理器中运行测试。

背景

我搜索了原生 C++ 的测试框架,正如许多有经验的程序员所说,Google Test Framework,也称为 GTest 是最好的。我用过它,它更高级,但它在 DOS 窗口中显示结果,并用颜色突出显示警报……但在这个 Visual Studio 测试项目中,情况不同,我们将使用 Visual Studio 来编写和运行我们的测试。

使用代码

我们将创建一个包含三个项目解决方案。

  1. 第一个是一个名为 DemoBusiness 的 Win32 库,它将包含我们的业务类。在这个库中,我将使用 Visual Studio 为我生成的类 CDemoBusiness
  2. // 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;
    }  
  3. 第二个项目是用于测试先前业务项目的原生单元测试项目。从文件 -> 新建 -> 项目 -> c++ -> 测试 -> 原生单元测试创建它。
  4. New native test project

    添加对 DemoBusiness 项目的依赖项。将输出 DemoBusiness.lib 添加到链接器输入,并将输出目录添加到 C++ 目录中的库目录,确保它们具有相同的输出目录,如果是共享链接而不是静态链接,建议使用静态链接。

    删除默认的 unittest1.cpp 文件,并添加一个新的 cpp 文件进行测试。我为我们的类创建了以下测试

    #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. 可选的主应用程序,它将使用业务类// 在我们的例子中是可选的,因为我们正在发现 VS2012 中的原生测试功能。
    • *在向 DemoBusiness 项目添加任何新逻辑后,转到测试并添加你的测试方法
    • *在 DemoBusiness 中进行任何更改后,构建它,然后构建测试模块,并从测试资源管理器运行所有测试
    • *所有 Logger::WriteMessage(L"") 注释将出现在输出窗口中,但选择 测试 在显示输出中。

关注点

有关原生单元测试的更多信息

  1. 使用 Microsoft.VisualStudio.TestTools.CppUnitTestFramework: http://msdn.microsoft.com/en-us/library/hh694604.aspx
  2. 在 VS11 中使用 Assert::ExpectException 进行原生单元测试: http://blogs.msdn.com/b/dgartner/archive/2012/04/22/using-assert-expectexception-with-native-unit-testing-in-vs11.aspx
  3. 使用测试资源管理器运行单元测试: http://msdn.microsoft.com/en-us/library/hh270865.aspx

这是测试的输出

© . All rights reserved.