【教程】在 Visual Studio 2015 上对 C++ 进行单元测试

更新中

前言

本文的测试环境是 Visual Studio 2015,高级别版本(如,2017,2022)的操作略有不同,但提供了更强大的测试功能,这两种版本 IDE 下的测试方式,可以阅读官方文档

环境

  1. os:win10
  2. IDE:Visual Studio 2015

Visual Studio 2015 提供的单元测试工具

  1. Test Explorer:可视化的测试辅助工具,可以在这个工具里查看测试的结果,它取代了以前版本的单元测试窗口。Test Explorer 可以适配包括第三方测试框架在内的各种测试框架
  2. Microsoft unit test framework for managed code:提供给托管代码的测试框架(托管代码一般是微软环境下的特定用于,是指可以运行在 .Net 平台上的,诸如 C#,F# 等语言)
  3. Microsoft unit test framework for C++:提供给 C++ 的测试框架
  4. IntelliTest:智能测试工具,仅供 C# 使用

创建 C++ 测试框架

在本节中,我们利用 Test Explorer 和 Visual Stuido 自带的 C++ 测试框架来完成一个简单语句的测试。

第一步,创建测试框架项目:在 solution 上右键,选择 [ Add ] - [ New Project ]
在这里插入图片描述
第二步[ Visual C++] - [ Test ] - [ Native Unit Test Project] 创建基于 C++ 的测试框架(注,Managed Test Project 用于托管代码的测试框架
在这里插入图片描述
第三步,打开测试文件:在 Solution Explorer 窗口中打开刚刚新建的测试框架项目,打开 测试文件
在这里插入图片描述
文件内部是下面的样子,简单解释一下结构 TEST_METHOD(TestMethod1) 表示一个测试单元,其中 TestMethod1 表示这个测试单元的名字,在 //TODO:Your test code here 这里填写你的测试语句,或者测试函数。
在这里插入图片描述
下面我们先来测试一段简单的代码逻辑(下一节将介绍如何测试函数)。这段逻辑如下,有 a,b 为输入,求 a,b 的和,并输入给 c,有 aimValue 作为基准值进行对比,来判断测试结果是否准确。

具体代码如下

	namespace UnitTest1
	{		
		TEST_CLASS(UnitTest1)
		{
		public:
			
			TEST_METHOD(TestMethod1)
			{
				// TODO: Your test code here
				int a = 10;
				int b = 20;
				int c = a + b;
				int aimValue = 30;
				Assert::AreEqual(c, aimValue);
			}
		};
	}

【注】Assert 是什么:这是微软测试框架提供的一个类似断言功能的类,它提供了大量函数方便你做结果的判断,测试框架将会根据这个类中的函数的结果作为测试是否通过的结果。
【注】Assert::AreEqual(c, aimValue) 用于判断 c 和 aimValue 是否相等,若相等则测试通过,否则不通过。
第四步,进行测试

  1. 简单介绍一下 Test 选项下的内容

    1. Run:运行选项
    2. Debug:可以在单元测试时进行 Debug 操作
    3. PlayList:测试用例
    4. Test setting:测试设置
    5. Windows:调出 Test Explorer 窗口
      在这里插入图片描述
  2. 设置测试默认处理器架构:一般现在我们选择 x64 的架构,如果不设置该选项,会报错不兼容的问题。[ Test ] - [ Test Settings ] - [ Default Processor Architecture ] - [ x64 ]
    在这里插入图片描述

  3. 然后我们运行测试。[ Test ] - [ Run ] - [ ALL Tests ]
    在这里插入图片描述

  4. 查看测试结果

    1. 最下面的 [ Output ] 窗口输出一些基本信息,如测试花费的时间
    2. 左侧的 [ Test Explorer ] 自动弹出,展示了测试的结果。这里,我们的测试用例 TestMethod1 成功通过了测试
      在这里插入图片描述第五步. 测试多个用例:刚刚我们测试了一个用例,叫做 TestMethod1,现在我们新增一个测试用例,用来展示一个错误的示例,叫做 FailTest1,该测试用例将加法逻辑改为减法,但我们的测试用例数据并未改变
    		namespace UnitTest1
    		{		
    			TEST_CLASS(UnitTest1)
    			{
    			public:
    				
    				TEST_METHOD(TestMethod1)
    				{
    					// TODO: Your test code here
    					int a = 10;
    					int b = 20;
    					int c = a + b;
    					int aimValue = 30;
    					Assert::AreEqual(c, aimValue);
    				}
    				
    				// add new test case
    				TEST_METHOD(FailTest1)
    				{
    					// TODO: Your test code here
    					int a = 10;
    					int b = 20;
    					// change a + b to a - b
    					int c = a - b;
    					int aimValue = 30;
    					Assert::AreEqual(c, aimValue);
    				}
    			};
    		}
    

第六步,运行测试,最终 FailTest1 未能通过测试
在这里插入图片描述

在测试项目内测试一个函数

在当前测试框架中创建两个文件,一个 test_fun.cpp 文件存放要测试的函数,一个 test_func.h 存放被测试函数的声明
在这里插入图片描述
我们在 test_fun.cpp 中实现一个乘法函数,非常简单,具体代码如下:

void Multiple(int a, int b, int *c)
{
	*c = a * b;
}

同时在 test_func.h 完成该函数的声明,这里就不贴图了。

在我们的测试文件(unittest1.cpp)中引入 test_func.h 头文件,然后新增一个测试单元叫做 TestFunc,具体代码如下:

#include "stdafx.h"
#include <iostream>
#include "CppUnitTest.h"

#include "test_func.h" // 引入我们的测试函数头文件

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace UnitTest1
{		
	TEST_CLASS(UnitTest1)
	{
	public:
		
		TEST_METHOD(TestMethod1)
		{
			// TODO: Your test code here
			// ...
		}

		TEST_METHOD(FailTest1)
		{
			// TODO: Your test code here
			// ...
		}

		TEST_METHOD(TestFunc)
		{
			// TODO: Your test code here
			int a = 10;
			int b = 20;
			int c = 0;

			// call Multiple
			Multiple(a, b, &c);
			 
			int aimValue = 200;
			Assert::AreEqual(c, aimValue);
		}
	};
}

然后运行测试,测试结果如下,TestFunc 测试通过
在这里插入图片描述

测试另一个 Project 的函数

现在假设我们有一个已经存在的项目叫做 TestClient,我需要测试其中的函数叫做 MainTest

第一步,我们还是在测试文件中新增一个测试单元叫做 TestProjectFunc,具体的代码如下:

TEST_METHOD(TestProjectFunc)
{
	// TODO: Your test code here
	int a = 10;
	int b = 20;
	int c = 0;

	MainTest(a, b, &c);

	int aimValue = 30;
	Assert::AreEqual(c, aimValue);
}

第二步,引入要测试函数所在的头文件 #include "../TestClient/TestClient.h"你也可以在测试项目属性页 “Include Directories” 中先配置全局的头文件导入路径,这样就只需要 #include "TestClient.h")
第三步,为测试项目添加外部引用,关联我们的 TestClient
在这里插入图片描述
在这里插入图片描述
第四步,添加额外依赖,也就是 MainTest 函数所在的源文件对应的 obj 文件
在这里插入图片描述
本例中,我的 MainTesttest.cpp 中,则对应需要依赖 test.obj 这个中间文件(和引入头文件类似,你也可以先在属性页配置好额外库文件的文件路径和要导入的中间对象文件 .obj
在这里插入图片描述
所有这些操作完成之后,运行测试,测试结果如下
在这里插入图片描述

测试一个类

  1. 描述:测试类的方式本质上和测试函数的方式一样。如果类在另一个 project 中,你需要引入头文件,配置好类实现所在的源文件对应的中间文件(.obj)
  2. 然后在测试单元中创建类,调用相应的类成员函数即可
  3. 一个简单的示例
#include "stdafx.h"
#include "CppUnitTest.h"
// EventSynchronize 类所在的头文件
#include "mycommunication.hpp"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace AlgExeUnitTest
{		
	TEST_CLASS(EventSynchronizeTest)
	{
	public:
		
		TEST_METHOD(EventSynchronizeTestExample)
		{
			int status = 0;

			EventSynchronize eventCreateTest;
			EventSynchronize eventOpenTest;

			// 类对象有一个 CreateEventWrap 成员方法
			status = eventCreateTest.CreateEventWrap();
			Assert::AreEqual(status , OK);

			// open
			status = (int)eventCreateTest.CreateEventWrap();
			Assert::AreEqual(status , OK); 
		}

	};
}

参考

  1. Visual Studio 2015 测试官方文档
  2. Visual Studio 使用教程:在Visual Studio中编写C / C ++的单元测试:2017 及更高版本
  3. vs2015单元测试总结——3种方法可用
  4. 关联测试与对象或库文件:2022 版本