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

#include "stdafx.h"
#include "CppUnitTest.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

#include <iostream>

using namespace std;

TEST_MODULE_INITIALIZE(ModuleInitialize)
{
	Logger::WriteMessage("In Module Initialize");
}

TEST_MODULE_CLEANUP(ModuleCleanup)
{
	Logger::WriteMessage("In Module Cleanup");
}

/*
第一次运行本unit test,使用Ctrl+R+A 运行全部测试.
以后你可以在Test Explorer窗口中运行指定的测试函数.
*/
namespace KagulaUnitTest
{		
	//模拟我的第一个待测试的function集合
	TEST_CLASS(myFirstFunctionSetForTest)
	{
	public:
		
		TEST_METHOD(TestMethod1)
		{
			//运行unit test不会打开控制台窗口,所以你也不会看到下面这条代码的任何std输出.
			cout << "hello,World!" << endl;
		}

		TEST_METHOD(TestMethod2)
		{
			//模拟耗时的操作.
			for (size_t i = 0; i < 1000; i++)
			{
				if ((i % 100) == 0)
				{
					//VisualStudio2017Update7.1有个很严重的缺陷,有时候,你改了代码,但是使用Test Explorer中的"Run selected Tests"菜单项,//运行的还是老的代码,这时候,你得rebuild solution后再运行.
					//所以修改代码后,修改下面的字符串输出,从output窗口中查看是不是修改已经生效很重要.
					Logger::WriteMessage("d.");
				}
			}//for
		}//test method
	};//test class

	//模拟我的第二个待测试的function集合
	TEST_CLASS(mySecondFunctionSetForTest)
	{
	public:

		//Assert的具体用法参考下面的地址
		//https://docs.microsoft.com/en-us/visualstudio/test/microsoft-visualstudio-testtools-cppunittestframework-api-reference#general_asserts
		TEST_METHOD(TestMethod2_1)
		{
			Logger::WriteMessage("TestMethod2_1");
			int expected = 0;
			int actual = 0;
			Assert::AreEqual(expected,actual);
			Assert::AreEqual(expected,actual,L"are not equal assert!");
		}

		TEST_METHOD(TestMethod2_2)
		{
			Logger::WriteMessage("TestMethod2_2");
			Assert::Fail(L"Fail");
		}
	};
}

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

#include <iostream>
using namespace std;

//这个函数用来演示你写的函数如何被"单元测试"工具调用
int myFunction()
{
	return 1;
}

int main(int argc,char* argv[])
{
	cout << "hello,World!" << endl;



	return 0;
}

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

//若不需要单元测试,把UNIT_TEST宏注释掉就可以了!
//否则exe程序会去找我们不需要的unit test依赖的dll.
#define UNIT_TEST

#ifdef UNIT_TEST
#include <CppUnitTest.h>

//假设这是我待做unit test测试的函数.begin
extern int myFunction();
//假设这是我待做unit test测试的函数.end


using namespace Microsoft::VisualStudio::CppUnitTestFramework;

BEGIN_TEST_MODULE_ATTRIBUTE()
TEST_MODULE_ATTRIBUTE(L"Date",L"2010/6/12")
END_TEST_MODULE_ATTRIBUTE()

TEST_MODULE_INITIALIZE(ModuleInitialize)
{
	Logger::WriteMessage("In Module Initialize");
}

TEST_MODULE_CLEANUP(ModuleCleanup)
{
	Logger::WriteMessage("In Module Cleanup");
}

/*
第一次运行本unit test,使用Ctrl+R+A 运行全部测试.
以后你可以在Test Explorer窗口中运行指定的测试函数.
*/
namespace KagulaUnitTest
{
	TEST_CLASS(myFunctionSetForTest)
	{
	public:

		//Assert的具体用法参考下面的地址
		//https://docs.microsoft.com/en-us/visualstudio/test/microsoft-visualstudio-testtools-cppunittestframework-api-reference#general_asserts
		TEST_METHOD(TestMethod2_1)
		{
			Logger::WriteMessage("TestMethod1");
			int expected = 0;
			int actual = myFunction();
			Assert::AreEqual(expected,L"are not equal assert!");
		}
	};
}
#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

#ifndef _LIB_H_
#define _LIB_H_

#ifdef _WIN32

#ifdef _WINDLL //VC2017新建项目后,改生成方式为dll,会自带这个宏定义.
#define LIB_API  extern "C" __declspec(dllexport)
#else
#define LIB_API  extern "C" __declspec(dllimport)
#endif

//我不喜欢编写非C语言风格的接口供调用者使用,除非时间紧.
#ifdef _WINDLL
#define CLASS_EXPORT __declspec(dllexport)
#else
#define CLASS_EXPORT __declspec(dllimport)

#endif

#else
//非Windows环境不需要那么麻烦直接定一个空白的就可以了.
#define  LIB_API 
#endif


LIB_API int add(int x,int y);

class CLASS_EXPORT MyDemoClass
{
public:
	int add(int a,int b);
};

#endif

CDemoLib.cpp

#include "CDemoLib.h"

int add(int x,int y)
{
	return x + y;
}

int MyDemoClass::add(int a,int b)
{
	return a + b;
}

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

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

#include "stdafx.h"
#include "CppUnitTest.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

#include "../UnitTest3/CDemoLib.h"

//添加All Configuration 库文件搜索路径: $(SolutionDir)$(Configuration);
#pragma comment(lib,"UnitTest3.lib")

namespace MyUnitTester
{		
	TEST_CLASS(UnitTest1)
	{
	public:
		
		TEST_METHOD(TestMethod1)
		{
			Logger::WriteMessage("MyUnitTester....");
			int expect = 0;
			int actual = add(0,0);
			//C风格接口  测试
			Assert::AreEqual(expect,L"are not equal assert!");

			MyDemoClass mdc;
			actual = mdc.add(0,0);
			//C++风格接口  测试
			Assert::AreEqual(expect,L"are not equal assert!");
		}
	};
}

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

Microsoft Unit Testing Framework for C++的更多相关文章

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. js中‘!.’是什么意思

  3. InnoDB 和 MyISAM 引擎恢复数据库,使用 .frm、.ibd文件恢复数据库

  4. Error: Cannot find module ‘node:util‘问题解决

    控制台 安装 Vue-Cli 最后一步出现 Error: Cannot find module 'node:util' 问题解决方案1.问题C:\Windows\System32>cnpm install -g @vue/cli@4.0.3internal/modules/cjs/loader.js:638 throw err; &nbs

  5. yarn的安装和使用(全网最详细)

    一、yarn的简介:Yarn是facebook发布的一款取代npm的包管理工具。二、yarn的特点:速度超快。Yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。超级安全。在执行代码之前,Yarn 会通过算法校验每个安装包的完整性。超级可靠。使用详细、简洁的锁文件格式和明确的安装算法,Yarn 能够保证在不同系统上无差异的工作。三、y

  6. 前端环境 本机可切换node多版本 问题源头是node使用的高版本

    前言投降投降 重头再来 重装环境 也就分分钟的事 偏要折腾 这下好了1天了 还没折腾出来问题的源头是node 使用的高版本 方案那就用 本机可切换多版本最终问题是因为nodejs的版本太高,导致的node-sass不兼容问题,我的node是v16.14.0的版本,项目中用了"node-sass": "^4.7.2"版本,无法匹配当前的node版本根据文章的提

  7. 宝塔Linux的FTP连接不上的解决方法

    宝塔Linux的FTP连接不上的解决方法常见的几个可能,建议先排查。1.注意内网IP和外网IP2.检查ftp服务是否启动 (面板首页即可看到)3.检查防火墙20端口 ftp 21端口及被动端口39000 - 40000是否放行 (如是腾讯云/阿里云等还需检查安全组)4.是否主动/被动模式都不能连接5.新建一个用户看是否能连接6.修改ftp配置文件 将ForcePassiveIP前面的#去掉 将19

  8. 扩展element-ui el-upload组件,实现复制粘贴上传图片文件,带图片预览功能

  9. 微信小程序canvas实现水平、垂直居中效果

    这篇文章主要介绍了小程序中canvas实现水平、垂直居中效果,本文图文实例代码相结合给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

  10. 使用HTML5做的导航条详细步骤

    这篇文章主要介绍了用HTML5做的导航条详细步骤,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

随机推荐

  1. static – 在页面之间共享数据的最佳实践

    我想知道在UWP的页面之间发送像’selectedItem’等变量的最佳做法是什么?创建一个每个页面都知道的静态全局变量类是一个好主意吗?

  2. .net – 为Windows窗体控件提供百分比宽度/高度

    WindowsForm开发的新手,但在Web开发方面经验丰富.有没有办法为Windows窗体控件指定百分比宽度/高度,以便在用户调整窗口大小时扩展/缩小?当窗口调整大小时,可以编写代码来改变控件的宽度/高度,但我希望有更好的方法,比如在HTML/CSS中.在那儿?

  3. 使用Windows Azure查询表存储数据

    我需要使用特定帐户吗?>将应用程序部署到Azure服务后,如何查询数据?GoogleAppEngine有一个数据查看器/查询工具,Azure有类似的东西吗?>您可以看到的sqlExpressintance仅在开发结构中,并且一旦您表示没有等效,所以请小心使用它.>您可以尝试使用Linqpad查询表格.看看JamieThomson的thispost.

  4. windows – SetupDiGetClassDevs是否与文档中的设备实例ID一起使用?

    有没有更好的方法可以使用DBT_DEVICEARRIVAL事件中的数据获取设备的更多信息?您似乎必须指定DIGCF_ALLCLASSES标志以查找与给定设备实例ID匹配的所有类,或者指定ClassGuid并使用DIGCF_DEFAULT标志.这对我有用:带输出:

  5. Windows Live ID是OpenID提供商吗?

    不,WindowsLiveID不是OpenID提供商.他们使用专有协议.自从他们的“测试版”期结束以来,他们从未宣布计划继续它.

  6. 如果我在代码中进行了更改,是否需要重新安装Windows服务?

    我写了一个Windows服务并安装它.现在我对代码进行了一些更改并重新构建了解决方案.我还应该重新安装服务吗?不,只需停止它,替换文件,然后重新启动它.

  7. 带有双引号的字符串回显使用Windows批处理输出文件

    我正在尝试使用Windows批处理文件重写配置文件.我循环遍历文件的行并查找我想要用指定的新行替换的行.我有一个’函数’将行写入文件问题是%Text%是一个嵌入双引号的字符串.然后失败了.可能还有其他角色也会导致失败.如何才能使用配置文件中的所有文本?尝试将所有“在文本中替换为^”.^是转义字符,因此“将被视为常规字符你可以尝试以下方法:其他可能导致错误的字符是:

  8. .net – 将控制台应用程序转换为服务?

    我正在寻找不同的优势/劣势,将我们长期使用的控制台应用程序转换为Windows服务.我们为ActiveMQ使用了一个叫做java服务包装器的东西,我相信人们告诉我你可以用它包装任何东西.这并不是说你应该用它包装任何东西;我们遇到了这个问题.控制台应用程序是一个.NET控制台应用程序,默认情况下会将大量信息记录到控制台,尽管这是可配置的.任何推荐?我们应该在VisualStudio中将其重建为服务吗?我使用“-install”/“-uninstall”开关执行此操作.例如,seehere.

  9. windows – 捕获外部程序的STDOUT和STDERR *同时*它正在执行(Ruby)

    哦,我在Windows上:-(实际上,它比我想象的要简单,这看起来很完美:…是的,它适用于Windows!

  10. windows – 当我试图批量打印变量时,为什么我得到“Echo is on”

    我想要执行一个简单的批处理文件脚本:当我在XP中运行时,它给了我预期的输出,但是当我在Vista或Windows7中运行它时,我在尝试打印值时得到“EchoisOn”.以下是程序的输出:摆脱集合表达式中的空格.等号(=)的两侧可以并且应该没有空格BTW:我通常在@echo关闭的情况下启动所有批处理文件,并以@echo结束它们,所以我可以避免将代码与批处理文件的输出混合.它只是使您的批处理文件输出更好,更清洁.

返回
顶部