WinUnit和CppUnit的比较分析
      两年前接触了CppUnit,因为它在C++的单体测试社区已经有着很多介绍以及成功的应用,当时没有经过太多的比较学习,就在的项目选用它。后来接触了WinUnit,尽管它有一些让能够让CppUnit显得“笨拙”的特点,但由于习惯了就没有做太多的改变。目前由于项目的需要,这两者之间的比较再次成为了话题,仅以此文梳理下,期待对那些还在两者之间选择的人有所帮助。
(1) 测试策略
      CppUnit的测试运行程序与测试都在同一二进制文件中完成(如图1所示),会使得这两者之间的界线模糊,并且需要编写实际调用测试运行功能的代码并将其放在某处。WinUnit实现了测试代码(以DLL形式提供的测试模块)和测试运行程序(WinUnit.exe)之间的分离(如图2所示),这种分离和NUnit和JUnit相似,但和CppUnit的方法有很大差距。所有测试都被编译和链接成单独的DLL,即测试模块。测试运行程序WinUnit.exe可以用来运行所有或部分的测试。通过检查PE文件的输出路径,所有测试模块中定义的测试都可以被识别到。实现的总体流程如下:
WinUnit和CppUnit的比较分析_第1张图片
图1 CppUnit测试的总体结构
WinUnit和CppUnit的比较分析_第2张图片
图2 WinUnit测试的总体结构
      不同的测试策略会导致不同的测试代码结构。WinUnit测试运行程序与测试的分离,有利于测试的维护和管理。
(2) 代码风格
      通用 WinUnit 测试函数总是以 BEGIN_TEST(testName) 开头,以 END_TEST 结束。在每个测试中,为验证各功能位往往要用到一个或多个 WIN_ASSERT 宏。实现例的模板如下:
WinUnit和CppUnit的比较分析_第3张图片
表1 WinUnit的实现例的模板
      而CppUnit则是需要在头文件内利用CPPUNIT_TEST_SUITE和CPPUNIT_TEST宏进行注册,然后同其他普通C++类一样在.cpp文件中进行实现。实现例的模板如下:
WinUnit和CppUnit的比较分析_第4张图片
表2 CppUnit的实现例的模板
      风格方面不同的人通常会有不同的选择,但我个人感觉WinUnit实现的测试代码更简洁,更优雅。
 
(3) 多平台支持
      在WinUnit之前,世界上并不乏针对 C++ 单元测试的其他选择。但WinUnit的作者认为现有的单元测试工具中存在一个问题:较之易于理解和可直接使用,可移植性的优先级更高。CppUnit的设计有着良好的跨平台支持,因此在学习、理解和使用它时所需的开销比预期的要高。而WinUnit 将仅在 Windows上运行。因此在跨平台应用或有跨平台应用的预期的时候在两者之间应该优选CppUnit,而对于纯Windows的应用,WinUnit可以节省不少实施中的开销。
 
(4) 运行
      WinUnit目前通过WinUnit.exe运行以DLL形式提供的测试模块,仅仅提供Console的结果查看。CppUnit 中把这种同时运行的测试案例的集合称为 TestSuite。而 TestRunner 则运行测试用例或者 TestSuite,具体管理所有测试用例的生命周期。目前提供了 三类TestRunner,包括TextUi::TestRunner(文本方式的TestRunner)、QtUi::TestRunner(QT方式的TestRunner)和MfcUi::TestRunner(MFC方式的TestRunner)。从结果显示的多样性来看,CppUnit优于WinUnit。
 
(5) Logger
      WinUnit和CppUnit都提供了Logger,可以支持输出指定到文件中,同时还提了扩展的可能。其中,CppUnit目前内置有TextOutputter和XmlOutputter类以支持文本文件和XML文件输出。而WinUnit目前仅内置有FileLogger类支持文本文件输出,但扩展比较容易。此外CppUnit的Logger配置需要通过硬编码实现,而WinUnit可以简单地通过命令行参数指定自定义Logger的DLL实现。
 
小结:
      WinUnit和CppUnit虽然属于xUnit,但由于设计理念和需求的不同,适合应用的环境也会有所不同。 总体来说如果是仅仅限定在Windows环境中,WinUnit在具备相似的功能下要比CppUnit容易使用并便于管理。