google gtest 快速入门_一线涯的博客-程序员信息网_google gtest

技术标签: C/C++  c++  开源项目  单元测试  gtest  google  

新博客链接

gtest 提供了一套优秀的 C++ 单元测试解决方案,简单易用,功能完善,非常适合在项目中使用以保证代码质量。

安装

官方传送门:googletest
现在官方已经把 gtest 和 gmock 一起维护,所以这个 git 仓库还包含了 gmock。

这里建议安装 gtest 1.7 release 版本(该安装方法对 1.8 不适用):

➜  ~ wget https://github.com/google/googletest/archive/release-1.7.0.tar.gz
➜  ~ tar xf release-1.7.0.tar.gz
➜  ~ cd googletest-release-1.7.0
➜  googletest-release-1.7.0 cmake -DBUILD_SHARED_LIBS=ON .
➜  googletest-release-1.7.0 make
➜  googletest-release-1.7.0 sudo cp -a include/gtest /usr/include
➜  googletest-release-1.7.0 sudo cp -a libgtest_main.so libgtest.so /usr/lib/

这样就 OK 了,可以用 sudo ldconfig -v | grep gtest 检查,看到下面就 OK 了:

libgtest.so -> libgtest.so
libgtest_main.so -> libgtest_main.so

使用

官方 WIKI:Gtest

断言

gtest 使用一系列断言的宏来检查值是否符合预期,主要分为两类:ASSERT 和 EXPECT。区别在于 ASSERT 不通过的时候会认为是一个 fatal 的错误,退出当前函数(只是函数)。而 EXPECT 失败的话会继续运行当前函数,所以对于函数内几个失败可以同时报告出来。通常我们用 EXPECT 级别的断言就好,除非你认为当前检查点失败后函数的后续检查没有意义。

基础的断言

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(val1,val2); EXPECT_EQ(val1,val2); val1 == val2
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(str1,str2); EXPECT_STREQ(str1,_str_2); 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(str1,str2); EXPECT_STRCASEEQ(str1,str2); 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

Samples

我们安装时下载的代码就包含了 10 个例子,可以直接在根目录下执行 make 并运行。进入 samples 文件夹,阅读每份功能代码和对应的测试文件,可以帮助我们较快入门。我们下面看一下简单的例子。

sample1

#include <limits.h>
#include "sample1.h"
#include "gtest/gtest.h"

// Tests factorial of negative numbers.
TEST(FactorialTest, Negative) {
  // This test is named "Negative", and belongs to the "FactorialTest"
  // test case.
  EXPECT_EQ(1, Factorial(-5));
  EXPECT_EQ(1, Factorial(-1));
  EXPECT_GT(Factorial(-10), 0);
}

...

TEST(IsPrimeTest, Positive) {
  EXPECT_FALSE(IsPrime(4));
  EXPECT_TRUE(IsPrime(5));
  EXPECT_FALSE(IsPrime(6));
  EXPECT_TRUE(IsPrime(23));
}

sample1 演示了简单测试用例的编写,主要使用了 TEST() 宏。这个宏的使用类似于:

TEST(test_case_name, test_name) {
 ... test body ...
}

一个 test_case_name 对应一个函数的测试用例,test_name 可以对应这个测试用例下的某个场景的测试集。这两个名字可以任意取,但应该是有意义的,而且不能包含下划线 _ 。

sample1 运行结果如下:
sample1

如果出错的话会提醒我们哪个用例错误,哪个检查点不通过,以及对应代码位置,非常棒。
test fail

sample3

sample3 用来演示一个测试夹具的使用。前面我们每个测试用例每个测试集间都是完全独立的,使用的数据也互不干扰。但如果我们使用的测试集需要使用一些相似的数据呢?或者有些相似的检查方法?这时就需要用到测试夹具了。

#include "sample3-inl.h"
#include "gtest/gtest.h"

// To use a test fixture, derive a class from testing::Test.
class QueueTest : public testing::Test {
 protected:  // You should make the members protected s.t. they can be
             // accessed from sub-classes.

  // virtual void SetUp() will be called before each test is run.  You
  // should define it if you need to initialize the varaibles.
  // Otherwise, this can be skipped.
  virtual void SetUp() {
    q1_.Enqueue(1);
    q2_.Enqueue(2);
    q2_.Enqueue(3);
  }

  // virtual void TearDown() will be called after each test is run.
  // You should define it if there is cleanup work to do.  Otherwise,
  // you don't have to provide it.
  //
  // virtual void TearDown() {
  // }

  // A helper function that some test uses.
  static int Double(int n) {
    return 2*n;
  }

  // A helper function for testing Queue::Map().
  void MapTester(const Queue<int> * q) {
    // Creates a new queue, where each element is twice as big as the
    // corresponding one in q.
    const Queue<int> * const new_q = q->Map(Double);

    // Verifies that the new queue has the same size as q.
    ASSERT_EQ(q->Size(), new_q->Size());

    // Verifies the relationship between the elements of the two queues.
    for ( const QueueNode<int> * n1 = q->Head(), * n2 = new_q->Head();
          n1 != NULL; n1 = n1->next(), n2 = n2->next() ) {
      EXPECT_EQ(2 * n1->element(), n2->element());
    }

    delete new_q;
  }

  // Declares the variables your tests want to use.
  Queue<int> q0_;
  Queue<int> q1_;
  Queue<int> q2_;
};

// When you have a test fixture, you define a test using TEST_F
// instead of TEST.

// Tests the default c'tor.
TEST_F(QueueTest, DefaultConstructor) {
  // You can access data in the test fixture here.
  EXPECT_EQ(0u, q0_.Size());
}

// Tests Dequeue().
TEST_F(QueueTest, Dequeue) {
  int * n = q0_.Dequeue();
  EXPECT_TRUE(n == NULL);

  n = q1_.Dequeue();
  ASSERT_TRUE(n != NULL);
  EXPECT_EQ(1, *n);
  EXPECT_EQ(0u, q1_.Size());
  delete n;

  n = q2_.Dequeue();
  ASSERT_TRUE(n != NULL);
  EXPECT_EQ(2, *n);
  EXPECT_EQ(1u, q2_.Size());
  delete n;
}

// Tests the Queue::Map() function.
TEST_F(QueueTest, Map) {
  MapTester(&q0_);
  MapTester(&q1_);
  MapTester(&q2_);
}

可以看到我们首先需要从 testing::Test 来派生一个自己的测试类QueueTest,在这个类里你可以定义一些必要的成员变量或者辅助函数,还可以定义 SetUp 和 TearDown 两个虚函数,来指定每个测试集运行前和运行后应该做什么。后面测试用例的每个测试集应该使用 TEST_F 宏,第一个参数是我们定义的类名,第二个是测试集的名称。

对于每个 TEST_F 函数,对应的执行过程如下:

  1. 创建测试夹具类(也就是说每个 TEST_F 都有一个运行时创建的夹具)。
  2. 用 SetUp 函数初始化。
  3. 运行测试集。
  4. 调用 TearDown 进行清理。
  5. delete 掉测试夹具。

其他

gtest 还提供了其他更灵活也更复杂的测试方法,可以参考 sample5 之后的例子。这里限于篇幅就不介绍了,而且就我而言即使在生产环境也不需要用到这么复杂的测试方法。

The End

最后的最后,希望大家把 gtest 用起来,单元测试对代码质量的保证作用真是非常大~

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jcjc918/article/details/52029455

智能推荐

openapi开放平台架构_适用于所有人的MicroProfile OpenAPI_cunfeng7797的博客-程序员信息网

openapi开放平台架构 MicroProfile OpenAPI主要用于将OpenAPI添加到JAX-RS端点。 在这篇博客中,我们将研究SmallRye实现如何在Quarkus中使用时,通过一些额外的功能来扩展此功能,并支持更多的Web框架。使用Quarkus 此处提供示例代码。 您也可以使用code.quarkus.io初始化项目-只需确保包括SmallRye OpenAPI扩展即可...

c# rar解压大小_C#解压RAR压缩文件_weixin_39611340的博客-程序员信息网

C# RAR压缩或解压文件using System;using System.Collections.Generic;using System.Text;using System.IO;using Microsoft.Win32;using System.Diagnostics;namespace Uni.UniCustoms{public class clsWinrar{/// /// 是否安...

C++与Qt实现MySQL数据库的增删改查_卧_听风雨的博客-程序员信息网

头文件MySQL数据库的安装与环境配置,网上大把,可参考:https://www.cnblogs.com/xtu-wlf1212/p/8764015.html头文件包含:#include &lt;QtSql/qsql.h&gt;#include &lt;QtSql/qsqldatabase.h&gt;#include &lt;QtSql/qsqlquery.h&gt;#include...

Sping学习笔记_kaibinsj的博客-程序员信息网

一、Spring包结构图: 二、              First Step举个简单的例子:(使用WSAD的包结构)Java Soucecom         ……..test                   ………domain                            Action.java                            LowerAction.jav

android 学习之路_黑键手记的博客-程序员信息网

源址:http://diycode.cc/topics/122本篇文章是从stormzhang那瞅到的,作为参考了解一下有一些链接可能还不是特别准确,因为我只能根据图片上的书或者资源的名字去Google可能的书籍,所以链接上有什么不对的,欢迎大家评论指出,我会及时更正。请参考原文:另一份 Android 开发学习路线图 帮助修改。谢谢。基础工具部分: 中

随便推点

字节跳动前端笔试总结(一)_前端小桃的博客-程序员信息网_字节跳动前端笔试题库

字节跳动笔试刚刚过去三两天,大厂真的很注重算法啊,经人推荐,我借了一本《剑指offer》先从案例学习一下简单的算法吧。这道题笔试的时候就做出来了,试探性的用了递归。。。我的答案欢迎指错...

Incorrect result size: expected 1, actual 0_心系蝶相印的博客-程序员信息网

HTTP Status 500 - Incorrect result size: expected 1, actual 0type Exception reportmessage Incorrect result size: expected 1, actual 0description The server encountered an internal error that

hdu 3535 分组背包+混合背包_OuterST的博客-程序员信息网

/* 题意:n组数据,容积为v,temp为种类,0类至少选一个,1类至多选一个,2自由选择,求最大价值分组混合背包,分别确定每一组的状态,种类0和2时,状态转移方程相同,只是初始化不同,*/#include #include #include using namespace std;#define INF -999999int dp[105][105];int main(){

【beautifulsoup】python标准库解析器解析网页问题解决_Jessie-via的博客-程序员信息网

使用python标准库解析(即BeautifulSoup(page, "html.parse"))出现网页解析问题如下,页面明明没有结束,却提前出现了,导致有些text没有了原本与之对应的标签,也就取不到了在尝试了很多种方法之后,发现是解析器的问题,所以更换了解析器BeautifulSoup(page, "html5lib")from bs4 import Beau

webstorm的ctrl+shift+F快捷键与微软输入法繁简体切换快捷键冲突_neimeng0的博客-程序员信息网

参考:https://www.zhihu.com/question/49313987设置里面可以改的,微软拼音输入法的选项藏的有点深,设置-语言-中文(选项)-微软拼音(选项)。如果觉得切换语言提示大,可以用alt+shift快捷键,不弹提示。...

Linux日志查找——正则表达式_ginkgo_biloba的博客-程序员信息网

文章目录基础文件内容一行以xx开头 ^一行以xx结尾 $只包含xx一个单词 ^ $空行 ^$词首 \\&lt; 或 \b词尾 \\&gt; 或 \b独立单词 \\&lt; \\&gt;非单词边界 \B连续次数匹配文件内容连续n个字符 \\{ \\}只出现n次的字符 \\&lt; \{ \}\\&gt;出现的次数在x与y之间 \\{x,y\\}至少连续出现x次 \\{x,\\}至多出现x次...

推荐文章

热门文章

相关标签