开源项目:https://github.com/cpputest/cpputest



CppUTest

CPPUTest是一个C/C++的单元测试框架


准备工作

你需要做这些准备工作:

编译源码(unix-based, cygwin, MacOSX)

  • Download latest version
  • autogen.sh
  • configure
  • make
  • make check
  • 如果你先想把CppUTest装进系统,你可以使用 "make install"
你也可以使用CMake,那样就能在Windows Visual Studio使用了

  • Download latest version
  • cmake CMakeList.txt
  • make

开始前,你还需要做如下工作:

在Makefile里增加头文件路径,如下:

       CPPFLAGS += -I(CPPUTEST_HOME)/include

在Makefile里增加内存泄露宏(需要额外的debug信息),如下:

         CXXFLAGS += -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorNewMacros.h

         CFLAGS += -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorMallocMacros.h

在Makefile里增加链接库,如下:

        LD_LIBRARIES = -L$(CPPUTEST_HOME)/lib -lCppUTest -lCppUTestExt


做完之后,你就可以写你的第一个test了:

TEST_GROUP(FirstTestGroup)
{
};

TEST(FirstTestGroup, FirstTest)
{
   FAIL("Fail me!");
}


命令行开关

-v: 详细信息,打印每个运行test的名字

-r#:重复多次执行test,默认情况是1次,#号如果没有指定则是2.这个开关在你定位内存泄露问题是会十分方便

-g:只运行指定名字的Test组

-n:只运行指定名字的Test


Test 宏

  • TEST(group, name) - 定义一个Test
  • IGNORE_TEST(group, name) - 关闭执行一个Test
  • TEST_GROUP(group) - 声明一个Test组. 这也会创建一个被别的库所需要的链接.
  • TEST_GROUP_BASE(group, base) - 和TEST_GROUP一样, 只是使用了和UTest不一样的基类
  • TEST_SETUP() - 在TEST_GROUP中声明了一个空的setup方法 - 声明一个 void setup()也是同样的效果
  • TEST_TEARDOWN() - 在TEST_GROUP里声明一个空的teardown方法
  • IMPORT_TEST_GROUP(group) - 从库中导入一个指定的组. 需在main函数中调用.

Set up and tear down

  • 每个TEST_GROUP 可能包含一个 setup和teardown 方法.
  • setup() 在test 前调用,而teardown() 在test 后调用.

Assertion(断言) 宏

以下的宏失败将导致当前test直接退出

  • CHECK(boolean condition) - 检查布尔结果
  • CHECK_TRUE(boolean condition) - 检查是否正确
  • CHECK_FALSE(boolean condition) - 检查是否错误
  • CHECK_EQUAL(expected, actual) - 检查等号左后是否相等. 如果一个类重载了==操作符,那么就可以比较同属这个类的两个实例.
  • STRCMP_EQUAL(expected, actual) - 用strcmp检查两个字符串是否相等
  • LONGS_EQUAL(expected, actual) - 比较两个数
  • BYTES_EQUAL(expected, actual) - 比较两个8比特数
  • POINTERS_EQUAL(expected, actual) - 比较两个 const void *指针
  • DOUBLES_EQUAL(expected, actual, tolerance) - 在一定公差范围内比较两个浮点数
  • FAIL(text) - 返回失败

使用TestPlugin构建default check

  • CppUTest 支持使用插件中的检查函数
  • TestPlugin从TestPlugin类中派生而来并且可以通过installPlugin方法插入到TestRegistry.
  • 所有的TestPlugins 在运行test前后被调用 (就像 Setup和Teardown一样). TestPlugins一般在main函数中被插入.
  • TestPlugins可以被用来像系统稳定性和资源操作如文件、内存、网络连接清理等.
  • 在CppUTest, 默认启用了内存泄露检查的插件

main函数里使用TestPlugin的例子:

int main(int ac, char** av)
{
   LogPlugin logPlugin;
   TestRegistry::getCurrentRegistry()->installPlugin(&logPlugin);
   int result = CommandLineTestRunner::RunAllTests(ac, av);
   TestRegistry::getCurrentRegistry()->resetPlugins();
   return result;
}


内存泄露检测

  • 一个特定平台的内存泄露检测机制是提供的.
  • 如果一个test失败了,并且在失败之前申请了内存,而这块内存也没有在TearDown 里被清理, 那么内存泄露将被报告. 最后是在已经排除了其他错误的情况下定位内存泄露问题.
  • 有些代码使用 lazy initialization,会出现看起来像内存泄露实际不是的情况(例如: gcc 早期版本中使用的stringstream). 有一种情况是一些标准库调用申请一些资源但是没有主动释放知道main()函数结束(或者根本没有).要找出内存泄露点就是要处理lazy initialization,设置 -r 开关跑两次tests. 这种情况的标志就是第一次跑的时候显示内存泄露但是第二次跑又显示没有。当两次都显示有泄露,那么你就需要找出真正泄露的地方了.

内存泄露检测是怎么实现的?

  • 在setup()前已经记录了内存使用情况
  • 在teardown()之后会记录另一个内存使用情况,将这与原先的进行比较
  • Visual Studio里MS将使用到调试堆的能力
  • GCC使用的是一个简单的new/delete计数,它会记录所有的new, new[], delete and delete[]操作

如果你有一些内存泄露的代码无法修改或者不想修改,你可以告诉TEST忽略特定的内存泄露点就像下面这个例子:

TEST(MemoryLeakWarningTest, Ignore1)
{
    EXPECT_N_LEAKS(1);
    char* arrayToLeak1 = new char[100];
}


Example Main

#include "UnitTestHarness/CommandLineTestRunner.h"

int main(int ac, char** av)
{
  return CommandLineTestRunner::RunAllTests(ac, av);
}

IMPORT_TEST_GROUP(ClassName)


Example Test

#include "UnitTestHarness/TestHarness.h"
#include "ClassName.h"

TEST_GROUP(ClassName)
{
  ClassName* className;

  void setup()
  {
    className = new ClassName();
  }
  void teardown()
  {
    delete className;
  }
}

TEST(ClassName, Create)
{
  CHECK(0 != className);
  CHECK(true);
  CHECK_EQUAL(1,1);
  LONGS_EQUAL(1,1);
  DOUBLES_EQUAL(1.000, 1.001, .01);
  STRCMP_EQUAL("hello", "hello");
  FAIL("The prior tests pass, but this one doesn't");
}




Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐