单元测试工具 GTest/Gmock(一)

编译安装

  • 配置编译工具
    • 编译Google Test 需要cmake2.6 版本以及上。
      yum list | grep cmake # 
      cmake --version  # 查看 cmake 版本
      
    • 支持C++11

这里以Gtest 1.8.0 安装为例,项目地址:https://github.com/google/googletest/

  • 获取源码
    wget https://github.com/google/googletest/archive/release-1.8.0.tar.gz
    tar -zxvf release-1.8.0.tar.gz
    
  • 编译安装
    cmake .  
    make && make install
    
    安装默认会将:
    -- Installing: /usr/local/lib/libgmock.a
    -- Installing: /usr/local/lib/libgmock_main.a
    -- Installing: /usr/local/lib/libgtest.a
    -- Installing: /usr/local/lib/libgtest_main.a
    
  • 测试:
    • 测试代码
      #include <stdio.h>
      #include <gtest/gtest.h>
      
      int add(int a, int b)  {  return a+b;  }
      
      TEST(MyTest, AddTest) {  EXPECT_EQ(add(1, 2), 3);  }
      
      int main(int argc, char *argv[]) {
          ::testing::InitGoogleTest(&argc, argv);
          return RUN_ALL_TESTS();
      }
      
    • 编译
      g++ -o test test.cpp -lgtest -lgtest_main -lpthread
      
    • 运行输出
      [==========] Running 1 test from 1 test case.
      [----------] Global test environment set-up.
      [----------] 1 test from MyTest
      [ RUN      ] MyTest.AddTest
      [       OK ] MyTest.AddTest (0 ms)
      [----------] 1 test from MyTest (0 ms total)
      
      [----------] Global test environment tear-down
      [==========] 1 test from 1 test case ran. (0 ms total)
      [  PASSED  ] 1 test.
      

jenkins 集成

GTest结果可以输出为xml文件的形式,配合第三方工具可以将其转为html网页形式。可以配合jenkins使用实现测试报告可视化。


基本使用介绍

官方文档:https://github.com/google/googletest/blob/master/googletest/docs/primer.md

如果局部测试使用了EXPECT系列函数,它将保证本次局部测试结果不会影响之后的流程。但是ASSERT系列在出错的情况下,当前测试特例中剩下的流程就不走了。

Testsuit 和 Testcase
断言
  • 布尔值类型检查

    Fatal assertion Nonfatal assertion Verifies
    ASSERT_TRUE(condition); EXPECT_TRUE(condition); condition is true
    ASSERT_FALSE(condition); EXPECT_FALSE(condition); condition is false
  • 数值类型检查

    Fatal assertion Nonfatal assertion Verifies
    ASSERT_EQ(expected, actual); EXPECT_EQ(expected, actual); expected == actual
    ASSERT_NE(val1, val2); EXPECT_NE(val1, val2); val1 != val2
    ASSERT_LT(val1, val2); EXPECT_LT(val1, val2); val1 < val2
    ASSERT_LE(val1, val2); EXPECT_LE(val1, val2); val1 <= val2
    ASSERT_GT(val1, val2); EXPECT_GT(val1, val2); val1 > val2
    ASSERT_GE(val1, val2); EXPECT_GE(val1, val2); val1 >= val2
  • 字符串类型检查

    Fatal assertion Nonfatal assertion Verifies
    ASSERT_STREQ(expected_str, actual_str); EXPECT_STREQ(expected_str, actual_str); the two C strings have the same content
    ASSERT_STRNE(str1, str2); EXPECT_STRNE(str1, str2); the two C strings have different content
    ASSERT_STRCASEEQ(expected_str, actual_str); EXPECT_STRCASEEQ(expected_str, actual_str); the two C strings have the same content, ignoring case
    ASSERT_STRCASENE(str1, str2); EXPECT_STRCASENE(str1, str2); the two C strings have different content, ignoring case
  • 异常检查

  • 类型检查

自定义输出
事件

gtest提供了多种事件机制,非常方便可以在测试前后做些自定义的动作。

  1. 全局的,所有案例执行前后。
  2. TestSuite级别的,在某一批案例中第一个案例前,最后一个案例执行后。
  3. TestCase级别的,每个TestCase前后。
  • 全局
    要实现全局事件,必须写一个类,继承testing::Environment类,实现里面的SetUp和TearDown方法。

    class FooEnvironment : public testing::Environment
    {
    public:
        virtual void SetUp()  {  std::cout << "Foo FooEnvironment SetUP" << std::endl;  }
        virtual void TearDown()  {  std::cout << "Foo FooEnvironment TearDown" << std::endl;  }
    };
    
    TEST(GlobalTest0, test00)  {  EXPECT_EQ(1, 1);  };
    TEST(GlobalTest0, test01)  {  EXPECT_EQ(1, 1);  };
    TEST(GlobalTest1, test10)  {  EXPECT_EQ(1, 1);  };
    
    int main(int argc, char**argv)
    {
        testing::AddGlobalTestEnvironment(new FooEnvironment);
        testing::InitGoogleTest(&argc, argv);
        return RUN_ALL_TESTS();
    }
    
    1.png
  • TestSuit

    class MyTestSuite0 : public testing::Test
    {
    protected:
        static void SetUpTestSuite()  {  cout << "TestSuite event0 : start" << endl;  }
        static void TearDownTestSuite()  {  cout << "TestSuite event0 : end" << endl;  }
    };
    
    TEST_F(MyTestSuite0, test0) {  EXPECT_EQ(1, 1);  }
    TEST_F(MyTestSuite0, test1) {  EXPECT_EQ(1, 1);  }
    TEST_F(MyTestSuite0, test2)  {  EXPECT_EQ(1, 1);  }
    
    int main(int argc, char** argv)
    {
        testing::InitGoogleTest(&argc, argv);
        return RUN_ALL_TESTS();
    }
    

    在编写测试案例时,我们需要使用TEST_F这个宏,第一个参数必须是我们上面类的名字,代表一个TestSuite。

  • TestCase

    class MyTestCase0 : public testing::Test
    {
    protected:
        virtual void SetUp()  {  cout << "TestCase event0 : start" << endl;  }
        virtual void TearDown()  {  cout << "TestCase event0 : end" << endl;  }
    };
    
    TEST_F(MyTestCase0, test0)  {  EXPECT_EQ(1, 1);  }
    TEST_F(MyTestCase0, test1)  {  EXPECT_EQ(1, 1);  }
    TEST_F(MyTestCase1, test0)  {  EXPECT_EQ(1, 1);  }
    
    int main(int argc, char** argv)
    {
        testing::InitGoogleTest(&argc, argv);
        return RUN_ALL_TESTS();
    }
    
    3.png
参数化
死亡测试
运行测试
gmock

参考资料

  1. http://hh-yzm.com/index.php/archives/30/
  2. https://zhuanlan.zhihu.com/p/34497162
  3. http://www.ibm.com/developerworks/cn/linux/l-cn-cppunittest/
  4. http://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html
  5. http://www.ibm.com/developerworks/cn/linux/l-cn-cppunittest/>
  6. http://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,194评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,058评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,780评论 0 346
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,388评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,430评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,764评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,907评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,679评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,122评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,459评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,605评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,270评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,867评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,734评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,961评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,297评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,472评论 2 348