Microsoft Unit Testing Framework for C++

前端之家收集整理的这篇文章主要介绍了Microsoft Unit Testing Framework for C++前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
Author: kagula
Date: 2018-05-11

Introduction

VC自带多个VC++单元测试工具,其中Microsoft Unit Testing Framework原生支持Test Explorer,这里通过三个例子来学习Microsoft Unit Testing Framework.


Environment

[1]Visual Studio 2017,update 7.1


Content

一、最简单的测试
这种情况只发生在“测试驱动”编码方式中,现实世界我很少用到,这里只是为了大致有个了解。
Step1:新建我们的第一个测试单元UnitTest1,新建solution
Visual C++ -> Test -> Native Unit Test Project

Step2:
用下面的代码替代建立的默认模板

unittest1.cpp

  1. #include "stdafx.h"
  2. #include "CppUnitTest.h"
  3.  
  4. using namespace Microsoft::VisualStudio::CppUnitTestFramework;
  5.  
  6. #include <iostream>
  7.  
  8. using namespace std;
  9.  
  10. TEST_MODULE_INITIALIZE(ModuleInitialize)
  11. {
  12. Logger::WriteMessage("In Module Initialize");
  13. }
  14.  
  15. TEST_MODULE_CLEANUP(ModuleCleanup)
  16. {
  17. Logger::WriteMessage("In Module Cleanup");
  18. }
  19.  
  20. /*
  21. 第一次运行本unit test,使用Ctrl+R+A 运行全部测试.
  22. 以后你可以在Test Explorer窗口中运行指定的测试函数.
  23. */
  24. namespace KagulaUnitTest
  25. {
  26. //模拟我的第一个待测试的function集合
  27. TEST_CLASS(myFirstFunctionSetForTest)
  28. {
  29. public:
  30. TEST_METHOD(TestMethod1)
  31. {
  32. //运行unit test不会打开控制台窗口,所以你也不会看到下面这条代码的任何std输出.
  33. cout << "hello,World!" << endl;
  34. }
  35.  
  36. TEST_METHOD(TestMethod2)
  37. {
  38. //模拟耗时的操作.
  39. for (size_t i = 0; i < 1000; i++)
  40. {
  41. if ((i % 100) == 0)
  42. {
  43. //VisualStudio2017Update7.1有个很严重的缺陷,有时候,你改了代码,但是使用Test Explorer中的"Run selected Tests"菜单项,//运行的还是老的代码,这时候,你得rebuild solution后再运行.
  44. //所以修改代码后,修改下面的字符串输出,从output窗口中查看是不是修改已经生效很重要.
  45. Logger::WriteMessage("d.");
  46. }
  47. }//for
  48. }//test method
  49. };//test class
  50.  
  51. //模拟我的第二个待测试的function集合
  52. TEST_CLASS(mySecondFunctionSetForTest)
  53. {
  54. public:
  55.  
  56. //Assert的具体用法参考下面的地址
  57. //https://docs.microsoft.com/en-us/visualstudio/test/microsoft-visualstudio-testtools-cppunittestframework-api-reference#general_asserts
  58. TEST_METHOD(TestMethod2_1)
  59. {
  60. Logger::WriteMessage("TestMethod2_1");
  61. int expected = 0;
  62. int actual = 0;
  63. Assert::AreEqual(expected,actual);
  64. Assert::AreEqual(expected,actual,L"are not equal assert!");
  65. }
  66.  
  67. TEST_METHOD(TestMethod2_2)
  68. {
  69. Logger::WriteMessage("TestMethod2_2");
  70. Assert::Fail(L"Fail");
  71. }
  72. };
  73. }

Step3:
使用菜单项[test]->[Run]->[All Tests]或则直接使用快捷键Ctrl+R+A
而不是习惯的F5或Ctrl+F5,之后会出现Test Explorer子窗口,如下图。


Output子窗口,Show output from下拉框选项改为Tests,然后你就可以看到单元测试项目的输出


二、对已存exe的测试这才是我最常见的使用场合

Step1:

建个简单的console程序c++项目,用来模拟已经存在的EXE程序项目

我写了个很简单的代码Source.cpp

  1. #include <iostream>
  2. using namespace std;
  3.  
  4. //这个函数用来演示你写的函数如何被"单元测试"工具调用
  5. int myFunction()
  6. {
  7. return 1;
  8. }
  9.  
  10. int main(int argc,char* argv[])
  11. {
  12. cout << "hello,World!" << endl;
  13.  
  14.  
  15.  
  16. return 0;
  17. }

Step2:为项目添加Unit Test依赖的头文件和库文件搜索路径.
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\VS\UnitTest\include
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\VS\UnitTest\lib

Step3:
使用下面的步骤添加unit test文件
Solution Explorer -> Add -> New Item -> C++ Unit Test.

如果没有“C++ Unit Test”模板,就添加个普通的cpp文件

Test.cpp

  1. //若不需要单元测试,把UNIT_TEST宏注释掉就可以了!
  2. //否则exe程序会去找我们不需要的unit test依赖的dll.
  3. #define UNIT_TEST
  4.  
  5. #ifdef UNIT_TEST
  6. #include <CppUnitTest.h>
  7.  
  8. //假设这是我待做unit test测试的函数.begin
  9. extern int myFunction();
  10. //假设这是我待做unit test测试的函数.end
  11.  
  12.  
  13. using namespace Microsoft::VisualStudio::CppUnitTestFramework;
  14.  
  15. BEGIN_TEST_MODULE_ATTRIBUTE()
  16. TEST_MODULE_ATTRIBUTE(L"Date",L"2010/6/12")
  17. END_TEST_MODULE_ATTRIBUTE()
  18.  
  19. TEST_MODULE_INITIALIZE(ModuleInitialize)
  20. {
  21. Logger::WriteMessage("In Module Initialize");
  22. }
  23.  
  24. TEST_MODULE_CLEANUP(ModuleCleanup)
  25. {
  26. Logger::WriteMessage("In Module Cleanup");
  27. }
  28.  
  29. /*
  30. 第一次运行本unit test,使用Ctrl+R+A 运行全部测试.
  31. 以后你可以在Test Explorer窗口中运行指定的测试函数.
  32. */
  33. namespace KagulaUnitTest
  34. {
  35. TEST_CLASS(myFunctionSetForTest)
  36. {
  37. public:
  38.  
  39. //Assert的具体用法参考下面的地址
  40. //https://docs.microsoft.com/en-us/visualstudio/test/microsoft-visualstudio-testtools-cppunittestframework-api-reference#general_asserts
  41. TEST_METHOD(TestMethod2_1)
  42. {
  43. Logger::WriteMessage("TestMethod1");
  44. int expected = 0;
  45. int actual = myFunction();
  46. Assert::AreEqual(expected,L"are not equal assert!");
  47. }
  48. };
  49. }
  50. #endif
Step4:
把项目的Configuration Type属性从原来的Application (.exe)改为Dynamic Library (.dll)
否则你单元测试代码是不能正常运行的。

Step5:
使用Ctrl+R+A运行所有的单元测试,或使用主菜单
Test->Run->All->Tests菜单命令运行所有单元测试。
接下来你可以探索Test Explorer窗口里的unit test功能的。

Final Step:
[1]
如果你项目unit test没问题了,再把project的Configuration Type属性 改回Application (.exe)
[2]
如果改回EXE后,Ctrl+F5运行程序,console一闪而过,使用下面的设置
Configuration Properties -> Linker -> System -> SubSystem -> Console(/SUBSYSTEM:CONSOLE)

三、对已存dll项目的测试
Step1:新建个空白项目,当作是我们待测的现存dll项目。

Installed -> Visual C++ -> General -> Empty Project
新起项目名称为UnitTest3
Configuration Type 设为 Dynamic Library(.dll)
这样编译源代码后会生成dll lib等两个文件.

我这个项目,由两个原文件组成,源码内容如下

CDemoLib.h

  1. #ifndef _LIB_H_
  2. #define _LIB_H_
  3.  
  4. #ifdef _WIN32
  5.  
  6. #ifdef _WINDLL //VC2017新建项目后,改生成方式为dll,会自带这个宏定义.
  7. #define LIB_API extern "C" __declspec(dllexport)
  8. #else
  9. #define LIB_API extern "C" __declspec(dllimport)
  10. #endif
  11.  
  12. //我不喜欢编写非C语言风格的接口供调用者使用,除非时间紧.
  13. #ifdef _WINDLL
  14. #define CLASS_EXPORT __declspec(dllexport)
  15. #else
  16. #define CLASS_EXPORT __declspec(dllimport)
  17.  
  18. #endif
  19.  
  20. #else
  21. //非Windows环境不需要那么麻烦直接定一个空白的就可以了.
  22. #define LIB_API
  23. #endif
  24.  
  25.  
  26. LIB_API int add(int x,int y);
  27.  
  28. class CLASS_EXPORT MyDemoClass
  29. {
  30. public:
  31. int add(int a,int b);
  32. };
  33.  
  34. #endif

CDemoLib.cpp

  1. #include "CDemoLib.h"
  2.  
  3. int add(int x,int y)
  4. {
  5. return x + y;
  6. }
  7.  
  8. int MyDemoClass::add(int a,int b)
  9. {
  10. return a + b;
  11. }

Step 2:
在当前solution下新建单元测试项目
Visual C++ -> Test -> Native Unit Test Project
我把project起名为MyUnitTester。

这个项目只有一个源文件,清单如下:

  1. #include "stdafx.h"
  2. #include "CppUnitTest.h"
  3.  
  4. using namespace Microsoft::VisualStudio::CppUnitTestFramework;
  5.  
  6. #include "../UnitTest3/CDemoLib.h"
  7.  
  8. //添加All Configuration 库文件搜索路径: $(SolutionDir)$(Configuration);
  9. #pragma comment(lib,"UnitTest3.lib")
  10.  
  11. namespace MyUnitTester
  12. {
  13. TEST_CLASS(UnitTest1)
  14. {
  15. public:
  16. TEST_METHOD(TestMethod1)
  17. {
  18. Logger::WriteMessage("MyUnitTester....");
  19. int expect = 0;
  20. int actual = add(0,0);
  21. //C风格接口 测试
  22. Assert::AreEqual(expect,L"are not equal assert!");
  23.  
  24. MyDemoClass mdc;
  25. actual = mdc.add(0,0);
  26. //C++风格接口 测试
  27. Assert::AreEqual(expect,L"are not equal assert!");
  28. }
  29. };
  30. }

Final Step:

然后你就可以Ctrl+R+A运行单元测试了。


Remark:

Q: 为什么不用boost.test?
A 因为在Visual Studio 中 Debug方式运行,console会一闪而过.


Reference

[1]<<Use the Microsoft Unit Testing Framework for C++ in Visual Studio>> https://docs.microsoft.com/en-us/visualstudio/test/how-to-use-microsoft-test-framework-for-cpp [2]<<Microsoft.VisualStudio.TestTools.CppUnitTestFramework API Reference>> https://docs.microsoft.com/en-us/visualstudio/test/microsoft-visualstudio-testtools-cppunittestframework-api-reference#general_asserts

猜你在找的Windows相关文章