Visual Studio中的C++ 单元测试

[原文发表地址] C++ Unit Testing in Visual Studio
[原文作者] Augustin Popa
[原文发表时间] 2017/4/19

测试在一个软件开发流中占有越来越重要的位置。在很多情况下,测试一个程序只是简单运行一下试着做一下就认为参与到了项目之中是远远不够的。在一个结构基点上能够测试代码单独的组件变得更加地必要。如果你是一个C++开发者并且对单元测试很感兴趣,你就需要留意一下Visual Studio的单元测试工具。这篇博客介绍了这个,他只是Visual Studio面向新用户系列的一部分。

这篇博客包含以下内容:

  1. 创建单元测试

  2. Microsoft本地C++单元测试框架

  3. 在IDE中使用测试资源管理器运行测试

  4. 判断单元测试覆盖率

创建单元测试

最简单最有条理的创建单元测试是为你的测试在Visual Studio上创建一个单独的工程。你可以在一个解决方案里创建你想要的多个测试项目,把它们连接到这个解决方案里面的任意数量的包含了你想测试的代码的其他Visual Studio工程上。假设你已经有了一些你要测试的代码,简单地按照如下这些步骤你就可以创建了:

  1. 右击你的解决方案,选择添加>新建>工程。点击Visual C++分类,选择测试子类。选择本地单元测试工程,给工程起个名字,然后点击确定。New Project Wizard for Testing
  2. Visual Studio将创建一个新的包含单元测试的工程,包含所有对本地测试框架的依赖项也已经创建起来。下一步要做的是为任何一个要测试的工程添加参考。右击单元测试工程,选择添加>参考…。Right-click Add > Reference
  3. 从你的测试工程中勾上任何你想要测试的的工程,然后点击OK.Add > Reference

你的单元测试工程现在可以访问你要测试的工程了。你现在可以编写测试代码了,只要你为你想访问的头文件添加#include声明就可以了。

注意: 这个方式你只是能够访问单元测试的公共函数。如果想访问单元测试私有的函数,你必须在被测试代码相同的类里面编写你的单元测试。

Microsoft本地C++ 单元测试框架

你可以使用随着Visual Studio一起发布的本地测试框架编写你的单元测试代码。框架定义了一系列的宏来简化语法。

如果你跟着做了之前的步骤,你现在应该已经有了一个根据你的主要代码创建的单元测试工程。在你的测试工程中打开unittest1.cpp,来看下如下提供的初始代码:Starting code provided when creating MSTest project.

首先,你将注意到依赖项已经被创建到测试框架了,所以你可以开始编写你所需的测试了。假设你已经在之前通过添加>参考把你的测试工程链接到你要测的工程了,你现在就可以简单的为你想要测试的代码的头文件添加#include声明。

测试可以通过使用TEST_CLASS和TEST_METHOD宏而被组织起来,它们将执行你期待的准确的函数。一个TEST_CLASS是有关的TEST_METHOD的一个集合,每一个TEST_METHOD都包含一个测试用例。你可以在括号里面给你的TEST_CLASS和TEST_METHOD起任何你想要的名字。使用使以后能区别标识每一个测试用例或者测试用例集的描述性的名字是个不错的主意。

让我们试着写一些基本的断言。在TODO解释中,写下:

Assert::AreEqual(1, 1);

这是一个基本的比较两个表达式相等的断言。第一个表达式表示期待值,第二个表达式表示你要测试的。如果断言通过,两边的结果必须相等。在这个示例中,这个测试用例总是通过的。你也可以测试两个表达式结果不相等的情况,如下:

Assert::AreNotEqual(1, 2);

这个,测试用例要通过的话,两个表达式必须不等于相同的结果。当然这种类型的断言是不普遍的,你可能发现它对验证你想避免特殊行为发生的边界值的用例非常有用。

这有一些其他的断言函数你可以尝试。可以看下,简单键入Assert::智能感应提供的整个列表。快速信息提示会出现在你在列表中选择的每一个断言上,在它们的格式和函数上提供更多的内容。你可以在MSDN上面找到整个Microsoft C++ 本地框架的参考功能

使用测试资源管理器在IDE中运行测试

使用Visual Studio,你没有被限制只能在命令行中运行单元测试。Visual Studio中的测试资源管理器窗口提供了一个简单的接口来运行,调试和并行测试执行。Test Explorer window

这是一个简单的过程。只要你把你的测试工程链接到你要测的工程下面,添加#include指向的文件包含你的单元测试代码,写一些断言,你就可以简单的运行整个build。测试资源管理器将发现你所有的单元测试用例并且把它们激活。

注意:在.NET中,有个功能叫Live Unit Testing 可以用。但是这个功能目前在C++中不支持,所以单元测试要被发现和执行只有在你运行生成之后。

运行你的单元测试,仅需要在测试资源管理器中点击运行全部链接。它将生成你的工程(如果工程已经是最新,这一步会被省略掉)然后运行你的测试用例。测试资源管理器会用一个勾选标记标识用例通过,会用X标识用例失败。执行结果的总结会提供在窗口的最底端。你可以点击任何失败的测试用例去查看它失败的原因,包含抛出的任何异常。每条单元测试用例的运行时间也会提供。对于真实的用例执行时间,测试是在解决方案的发布配置下进行而不是调试配置,它提供跟你的发布的应用程序几乎相似的更快的运行时间。

为了能够调试你运行的单元测试的代码(你可以停在断点或者向前),简单地使用测试> 调试来运行你的测试用例。

判断单元测试代码覆盖率

如果你用的是Visual Studio 企业版,   你可以在你的单元测试上测试代码覆盖率。假设你已经为你的工程创建好了单元测试,在IDE的最顶端在Visual Studio的主菜单上选择测试> 分析代码覆盖率就可以了。这样会打开你的测试总结代码覆盖数据的代码覆盖结果窗口。Code Coverage Results window

注意:有一个已知缺陷,如果在调试配置中没有选择/DEBUG:FULL,代码覆盖是不会工作的。默认情况下,配置中设的是/DEBUG:FASTLINK. 你可以通过如下步骤转换到/DEBUG:FULL:

  1. 右击测试工程选择属性。
  2. 连接器> 调试> 生成调试信息
  3. 设成生成经过优化以共享和发布的调试信息 (/DEBUG:FULL).选项。

代码覆盖结果窗口提供了一个叫色彩化显示代码覆盖的选项,它将基于是否被覆盖来给代码着色。Code Coverage coloring

代码覆盖是数代码段,一个代码段是一段带有一个入口和出口的代码。如果一个代码段被通过至少一次,它就是被覆盖的。

关于C++ Unit测试的更多信息,包含一些高级的话题,请查看以下MSDN文章: