【C++】Google Gtest测试框架的使用

时间:2024-04-05 14:24:13

本文首发于 ❄️慕雪的寒舍

gtest模块的安装参考站内教程 ubuntu安装google gtest

本文使用的gtest版本为1.14.0;

1.gtest是用来干嘛的?

google gtest是一个c++的单元测试模块,它提供了一系列规范化的宏,来帮助我们进行函数的单元测试。

image.png

单元测试你可以理解为测试我们编写好的每个函数模块,确保这些函数的功能不会影响其他函数,并保证函数能依照预期的功能进行工作。

要知道,绝大部分的软件bug都是在设计、初次代码编写的过程中产生的,比如你写了一个add函数,但是错误的将运算符写成了-,add就变成sub函数了,如果这个add函数在其他功能模块完成之后才发现被写错,就闹大笑话了。

当然,上面这个add的例子并不合适,因为它太简单了。但实际项目中,就是由多个很简单的代码聚合而成的一个大软件模块。每一个看上去简单、不可能写错的地方,都有可能隐藏的出错的危险。

所以,这就需要我们在完成每个功能函数的编写后,通过单元测试来判断函数是否有问题。

2.gtest的代码基本框架

一般情况下,多模块的软件项目都会用cmake来实现批量化的编译和单元测试的运行。但本文只是对gtest模块使用的最基本教程,再加上我并没有学习cmake的使用,所以暂时使用g++直接对单模块进行编译并介绍gtest的测试宏。

Testing Reference | GoogleTest

比较常用的是TEST和TEST_F这两个测试宏,更多测试宏请参考官方文档中的介绍。

2.1 TEST 单元测试模块

在gtest中,一个单元测试模块长下面这样

TEST(TestSuiteName, TestName) {
  ... statements ...
}

你可以理解为,左侧是被测模块的名字,右侧是在这个被测模块中的某个测试的名字,statements是任意被测模块的代码;gtest框架建议使用大驼峰的命名方式,TEST的命名中不要带有_下划线。

比如我有一个模块A的单元测试,那么左侧可以填写为模块ATest,右侧填写为类中某个函数的测试。这两个名字可以随便起,但是在同一个TestSuiteName中不能有两个相同的TestName;

一个单元测试模块的成功与失败取决于内部定义的gtest断言宏,参考后文的介绍。

2.2 TEST_F 类测试模块

上述的TEST方式是用于测试普通函数的,还有一个TEST_F可以用于对类进行测试

TEST_F(TestFixtureName, TestName) {
  ... statements ...
}

此时左侧的TestFixtureName不再是随便起的了,你必须定义一个继承于testing::Test的测试类,该类可以定义成员变量或对被测目标进行初始化、销毁操作。

class MyClassTest : public testing::Test {
protected:  
    void SetUp() // 初始化,在每个TEST_F中都会被调用
    {}

    void TearDown() // 销毁,在每个TEST_F结束时都会调用
    {}
    
	// 可以定义一些成员变量,在TEST_F中能访问
    int _a;
};

最终的测试代码应该是下面这样的

class MyClassTest : public testing::Test {
  ...
};

TEST_F(MyClassTest, HasPropertyA) { ... }
TEST_F(MyClassTest, HasPropertyB) { ... }

2.3 简单示例

下面是一个简单的gtest单元测试编写的示例,包含测试单元体和main函数。一个文件里面可以写N个TEST或TEST_F,它们会按顺序执行。

#include <gtest/gtest.h>

// 一个函数测试
// 左侧是测试模块的名字,右侧是该模块测试的目的
TEST(ADDTEST, ADDTEST_TRUE)
{}

int main(int argc, char **argv)
{
	// 主函数
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

使用如下g++命令编译该代码,注意gtest是一个动态库,需要使用-lgtest进行链接。

g++ test.cpp -o test -lgtest

3.gtest提供的断言宏

官方文档:Assertions Reference | GoogleTest

gtest中提供的宏分为ASSERT和EXPECT两种,其中ASSERT宏会在检查到错误的时候直接终止单元测试用例的运行(注意是单个单元测试),而EXPECT不会。

TEST(EXP,EXP1)
{
	ASSERT_EQ(1,1); // 如果这个出错了,后续不会执行
	// 这里不会被执行	
}

TEST(EXP,EXP2)
{
	EXPECT_EQ(1,1); // 如果这个出错了,还是会继续往后执行这个模块的其他代码。
	// 这里的代码能被执行
}

单元测试运行结束后,gtest会给出测试失败的模块汇总。

3.1 相等/大小判断

ASSERT宏 EXPECT宏 功能 参数个数
ASSERT_TRUE EXPECT_TRUE 判真 1
ASSERT_FALSE EXPECT_FALSE 判假 1
ASSERT_EQ EXPECT_EQ 相等 2
ASSERT_NE EXPECT_NE 不相等 2
ASSERT_GT EXPECT_GT 第一个参数是否大于第二个参数 2
ASSERT_LT EXPECT_LT 小于(原理同上) 2
ASSERT_GE EXPECT_GE 大于等于 2
ASSERT_LE EXPECT_LE 小于等于 2
ASSERT_FLOAT_EQ EXPECT_FLOAT_EQ 单精度浮点数相等 2
ASSERT_DOUBLE_EQ EXPECT_DOUBLE_EQ 双精度浮点数相等 2
ASSERT_NEAR EXPECT_NEAR 浮点数是否接近(第三个参数为允许的误差值) 3
ASSERT_STREQ EXPECT_STREQ C字符串相等 2
ASSERT_STRNE EXPECT_STRNE C字符串不相等 2
ASSERT_STRCASEEQ EXPECT_STRCASEEQ C字符串相等(忽略大小写) 2
ASSERT_STRCASENE EXPECT_STRCASENE C字符串不相等(忽略大小写) 2
ASSERT_PRED1 EXPECT_PRED1 自定义谓词测试(有1到5级,对应不同参数个数的自定义函数) 2
ASSERT_THAT EXPECT_THAT 判断函数返回值是否符合给定的matcher(gtest提供的) 2

3.2 异常相关

除了上述这种判断大小和相等的宏,还有和异常以及程序崩溃相关的宏

ASSERT宏 EXPECT宏 作用 参数个数
ASSERT_THROW EXPECT_THROW 期待抛出指定异常,第一个参数是目标函数,第二个参数是异常类型 2
ASSERT_ANY_THROW EXPECT_ANY_THROW 期待抛出任何异常 1
ASSERT_NO_THROW EXPECT_NO_THROW 不希望抛出任何异常 1
ASSERT_EXIT EXPECT_EXIT 期望程序以指定错误码exit,且标准错误输出符合第三个参数的regex表达式 3
ASSERT_DEATH EXPECT_DEATH 期望程序错误退出(退出码非0),且标准错误输出符合第二个参数的regex表达式 2
ASSERT_DEBUG_DEATH EXPECT_DEBUG_DEATH 同上,但是在调试模式下测试;非调试模式下只会执行函数,不做判断。 2
ASSERT_DEATH_IF_SUPPORTED EXPECT_DEATH_IF_SUPPORTED 同DEATH,但是只有在支持的时候才会被调用,如果不支持则什么都不做。 2

3.3 直接表明成功和失败

还有两个宏是直接表明该单元测试是否成功,以及是否失败的。主动调用这两个宏会提前终止该单元测试用例。

SUCCEED(); // 成功
FAIL();    // 失败

3.4 添加失败信息

有的时候gtest默认提供的ASSERT宏不够我们的使用,你可以用自定义的判断,并在不符合预期的时候将这个错误信息添加进去,Gtest在最后汇总的时候也会显示出来。

// Generates a nonfatal failure, which allows the current function to continue running.
ADD_FAILURE();

// Generates a nonfatal failure at the file and line number specified.
ADD_FAILURE_AT(file_path,line_number);

这两个宏的效果和EXPECT类似,都允许继续往后执行该单元测试用例。

4.使用示例

大部分的使用都是一样的,下面只对几个有代表性的做使用示例;为了方便,只对ASSERT做示例,因为它的效果和EXPECT完全一致,上文已经提到了二者的区别了。

4.1 ASSERT_EXIT

ASSERT_EXIT有三个参数,分别为待测函数、退出码或退出信号、错误信息regex;待测函数必须以指定的错误码或错误信号退出程序,并在stderr中打印能被这个regex匹配的错误信息。

ASSERT_EXIT(statement,predicate,matcher);

第二个参数的可选项,分别代表错误退出码和收到的错误信号

// Returns true if the program exited normally with the given exit status code.
::testing::ExitedWithCode(exit_code);

// Returns true if the program was killed by the given signal.
// Not available on Windows.
::testing::KilledBySignal(signal_number);

第三个参数在官网上的描述是这样的

The parameter matcher is either a matcher for a const std::string&, or a regular expression (see Regular Expression Syntax)—a bare string s (with no matcher) is treated as ContainsRegex(s), not Eq(s).

如果传入一个普通字符串,则会判断stderr输出的内容是否包含该字符串。

下面是一个简单的示例,我们的函数调用了exit(1),使用ASSERT_EXIT来判断它是否以预期的错误码1退出程序。第三个参数.*是正则表达式,代表任意错误信息的匹配。

#include <gtest/gtest.h>
#include <iostream>
#include <unistd.h>


void test_exit()
{
    std::cerr << "test exit\n";
    exit(1);
    // int ret = 10/0;
}

TEST(EXPTEST, EXPTEST_EXIT)
{
    // 期望以错误码1退出
    ASSERT_EXIT(test_exit(),testing::ExitedWithCode(1),".*");
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

编译后的执行效果如下,我们的单元测试成功了,因为函数的确是以错误码1退出的。

❯ g++ test.cpp -o test -lgtest && ./test
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_EXIT
[       OK ] EXPTEST.EXPTEST_EXIT (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

那么如果换一个退出方式呢?比如因为除0错误退出

❯ g++ test.cpp -o test -lgtest && ./test
test.cpp: In function 'void test_exit()':
test.cpp:11:17: warning: division by zero [-Wdiv-by-zero]
   11 |     int ret = 10/0;
      |               ~~^~
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_EXIT
test.cpp:17: Failure
Death test: test_exit()
    Result: died but not with expected exit code:
            Terminated by signal 8
Actual msg:
[  DEATH   ] test exit
[  DEATH   ] 

[  FAILED  ] EXPTEST.EXPTEST_EXIT (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] EXPTEST.EXPTEST_EXIT

 1 FAILED TEST

这个时候单元测试就失败了,并会打印出失败行的位置和失败的原因。这里提到失败是因为受到了信号8,但我们预期是错误码1。

将预期修改为信号8,就能通过测试

void test_exit()
{
    std::cerr << "test exit\n";
    // exit(1);
    int ret = 10/0;
}

TEST(EXPTEST, EXPTEST_EXIT)
{
    // 期望以收到信号8退出
    ASSERT_EXIT(test_exit(),testing::KilledBySignal(8),".*");
}

注意这里的警告是g++编译器检测到除0错误后提供的,并非是运行时的错误。

❯ g++ test.cpp -o test -lgtest && ./test
test.cpp: In function 'void test_exit()':
test.cpp:11:17: warning: division by zero [-Wdiv-by-zero]
   11 |     int ret = 10/0;
      |               ~~^~
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_EXIT
[       OK ] EXPTEST.EXPTEST_EXIT (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

将第三个参数改为一个普通字符串,gtest会进行stderr输出是否包含该字符串的检查;

void test_exit()
{
    std::cerr << "test exit\n";
    int ret = 10/0;
}

TEST(EXPTEST, EXPTEST_EXIT)
{
    // 期望以收到信号退出
    ASSERT_EXIT(test_exit(),testing::KilledBySignal(8),"happy");
}

可以看到,单元测试失败的原因是“错误退出但是没有提供期望的error输出”。

❯ g++ test.cpp -o test -lgtest && ./test
test.cpp: In function 'void test_exit()':
test.cpp:10:17: warning: division by zero [-Wdiv-by-zero]
   10 |     int ret = 10/0;
      |               ~~^~
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_EXIT
test.cpp:16: Failure
Death test: test_exit()
    Result: died but not with expected error.
  Expected: contains regular expression "happy"
Actual msg:
[  DEATH   ] test exit
[  DEATH   ] 

[  FAILED  ] EXPTEST.EXPTEST_EXIT (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] EXPTEST.EXPTEST_EXIT

 1 FAILED TEST

如果在错误输出中包含happy字符串,则正常通过测试。

void test_exit()
{
    std::cerr << "test exit happy\n"; // 包含happy字符串
    int ret = 10/0;
}

TEST(EXPTEST, EXPTEST_EXIT)
{
    // 期望以收到信号退出
    ASSERT_EXIT(test_exit(),testing::KilledBySignal(8),"happy");
}
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_EXIT
[       OK ] EXPTEST.EXPTEST_EXIT (1 ms)
[----------] 1 test from EXPTEST (1 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (1 ms total)
[  PASSED  ] 1 test.

注意:函数内的assert错误对应的是信号6,如果需要用ASSERT_EXIT来捕捉assert错误,则需要使用testing::KilledBySignal(6)

4.2 ASSERT_DEATH

ASSERT_DEATH和ASSERT_EXIT宏的作用基本一致,只不过ASSERT_DEATH不需要我们传入期望退出的错误码或信号。此时任意非0错误码退出和任意信号退出都会被视为ASSERT_DEATH的测试成功情况。

EXPECT_DEATH(statement,matcher);
ASSERT_DEATH(statement,matcher);

这里的第二个参数和ASSERT_EXIT的第三个参数一致,可以是一个字符串,也可以是一个regex表达式。

示例代码和测试结果如下:

#include <gtest/gtest.h>
#include <iostream>
#include <unistd.h>


void test_exit()
{
    std::cerr << "test exit\n";
    exit(1);
}

TEST(EXPTEST, EXPTEST_EXIT)
{
    ASSERT_DEATH(test_exit(),".*");
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
❯ g++ test.cpp -o test -lgtest && ./test
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_EXIT
[       OK ] EXPTEST.EXPTEST_EXIT (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

ASSERT_DEATH只有在被测函数没有错误退出,或者以exit(0)退出的时候会出错。因为0号在操作系统中是进程退出的正常情况,非0才是错误信号。

❯ g++ test.cpp -o test -lgtest && ./test
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_EXIT
test.cpp:15: Failure
Death test: test_exit()
    Result: died but not with expected exit code:
            Exited with exit status 0
Actual msg:
[  DEATH   ] test exit
[  DEATH   ] 

[  FAILED  ] EXPTEST.EXPTEST_EXIT (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] EXPTEST.EXPTEST_EXIT

 1 FAILED TEST

注意,抛出异常并没有归结到DEATH和EXIT的判定范围内。

void test_exit()
{
    std::cerr << "test exit happy\n";
    // int ret = 10/0;
    throw std::runtime_error("123");
}

TEST(EXPTEST, EXPTEST_EXIT)
{
    ASSERT_DEATH(test_exit(),"happy");
}
❯ g++ test.cpp -o test -lgtest && ./test
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_EXIT
test.cpp:16: Failure
Death test: test_exit()
    Result: threw an exception.
 Error msg:
[  DEATH   ] test exit happy
[  DEATH   ] 
[  DEATH   ] test.cpp:16:: Caught std::exception-derived exception escaping the death test statement. Exception message: 123
[  DEATH   ] 

[  FAILED  ] EXPTEST.EXPTEST_EXIT (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] EXPTEST.EXPTEST_EXIT

 1 FAILED TEST

4.3 ASSERT_DEBUG_DEATH

对于ASSERT_DEBUG_DEATH,官方文档是这么描述的:

In debug mode, behaves the same as EXPECT_DEATH. When not in debug mode (i.e. NDEBUG is defined), just executes statement.

这里补充一下NDEBUG宏的作用,在标准库里面,它会控制assert是否起效果。如果一个程序define了NDEBUG宏(注意必须在引用<assert.h>头文件之前定义),那么assert将什么都不做。

可以看assert.h的源代码,当定义了NDEBUG宏后,assert会调用__ASSERT_VOID_CAST (0);在C++中这个cast是一个static_cast<void>,在C语言中是一个)void)的强转,反正都是啥都不干。

#if defined __cplusplus && __GNUC_PREREQ (2,95)
# define __ASSERT_VOID_CAST static_cast<void>
#else
# define __ASSERT_VOID_CAST (void)
#endif

/* void assert (int expression);

   If NDEBUG is defined, do nothing.
   If not, and EXPRESSION is zero, print an error message and abort.  */

#ifdef	NDEBUG

# define assert(expr)		(__ASSERT_VOID_CAST (0))

/* void assert_perror (int errnum);

   If NDEBUG is defined, do nothing.  If not, and ERRNUM is not zero, print an
   error message with the error text for ERRNUM and abort.
   (This is a GNU extension.) */

# ifdef	__USE_GNU
#  define assert_perror(errnum)	(__ASSERT_VOID_CAST (0))
# endif

#else /* Not NDEBUG.  */

下面是一个简单的测试示例,当我们没有定义NDEBUG的时候,ASSERT_DEBUG_DEATH和ASSERT_DEATH做的是相同的操作。

#include <gtest/gtest.h>
#include <iostream>
#include <unistd.h>


void test_exit()
{
    std::cerr << "test exit happy\n";
    exit(1);
}

TEST(EXPTEST, EXPTEST_EXIT)
{
    ASSERT_DEBUG_DEATH(test_exit(),"happy");
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
❯ g++ test.cpp -o test -lgtest && ./test
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_EXIT
[       OK ] EXPTEST.EXPTEST_EXIT (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

如果在文件开头定义了NDEBUG,那么ASSERT_DEBUG_DEATH则只会调用函数,并不会做错误信息的判断,如下所示,我们将函数中的exit删除,gtest也没有报告错误。

#define NDEBUG 1 // 一定要在开头定义
#include <gtest/gtest.h>
#include <iostream>
#include <unistd.h>


void test_exit()
{
    std::cerr << "test exit happy\n";
    // exit(1); // 没有错误退出
}

TEST(EXPTEST, EXPTEST_EXIT)
{
    ASSERT_DEBUG_DEATH(test_exit(),"happy");
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

可以看到,我们的函数并没有退出,但是由于定义了NDEBUG,ASSERT_DEBUG_DEATH宏没有报告错误。(去掉该宏,则会和ASSERT_DEATH一样提示出错)

❯ g++ test.cpp -o test -lgtest && ./test
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_EXIT
test exit happy
[       OK ] EXPTEST.EXPTEST_EXIT (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

4.4 ASSERT_THROW

调用对象应该抛出异常,并判断异常类型是否为期待类型。

#include <gtest/gtest.h>
#include <iostream>
#include <unistd.h>

void test_throw()
{
    throw std::runtime_error("test");
}

TEST(EXPTEST, EXPTEST_THROW)
{
    ASSERT_THROW(test_throw(),std::runtime_error);
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
❯ g++ test.cpp -o test -lgtest && ./test
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_THROW
[       OK ] EXPTEST.EXPTEST_THROW (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

当抛出的异常类型不一致的时候会出错

❯ g++ test.cpp -o test -lgtest && ./test
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_THROW
test.cpp:12: Failure
Expected: test_throw() throws an exception of type std::runtime_error.
  Actual: it throws std::length_error with description "123".

[  FAILED  ] EXPTEST.EXPTEST_THROW (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] EXPTEST.EXPTEST_THROW

 1 FAILED TEST

异常相关的还有两个

  • ASSERT_ANY_THROW不需要传入第二个参数,只关注目标函数应该抛出异常;
  • ASSERT_NO_THROW也只有一个参数,目标函数不应该抛出异常;

因为它们很简单,这里就不做演示了。

4.5 ASSERT_EQ/NE

相等和不相等的比较。

#include <gtest/gtest.h>
#include <iostream>
#include <unistd.h>


TEST(EXPTEST, EXPTEST_EQ)
{
    int ret = 10;
    ASSERT_EQ(ret,10);
    ASSERT_NE(ret,29);
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
❯ g++ test.cpp -o test -lgtest && ./test
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_EQ
[       OK ] EXPTEST.EXPTEST_EQ (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

ASSERT_FLOAT_EQ和ASSERT_DOUBLE_EQ是在比较的基础上允许一定的浮点数精度误差值。如果你需要比较两个浮点数,请使用对应的浮点数类型比较宏,而不要直接使用ASSERT_EQ;

4.6 ASSERT_GE/LE

注意,大小写比较都是左和右直接按顺序比较的,比如GE是判断左边是否大于右边(不要搞反顺序了)

TEST(EXPTEST, EXPTEST_GE)
{
    int ret = 10;
    ASSERT_GE(ret,5);
    ASSERT_LE(ret,29);
}
❯ g++ test.cpp -o test -lgtest && ./test
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_EQ
[       OK ] EXPTEST.EXPTEST_EQ (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

4.7 ASSERT_NEAR

该宏提供了第三个参数,在浮点数比较时允许一定的误差值。官网文档说明是保证val1和val2不超过abs_error的误差边界。

EXPECT_NEAR(val1,val2,abs_error)
ASSERT_NEAR(val1,val2,abs_error)
// Verifies that the difference between val1 and val2 does not exceed the absolute error bound abs_error.

下面是一个示例

#include <gtest/gtest.h>
#include <iostream>
#include <unistd.h>


TEST(EXPTEST, EXPTEST_NEAR)
{
    ASSERT_NEAR(3.14,3.15,0.01);
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

因为两个数字的差距的确在0.01的误差区间,所以可以通过测试。

❯ g++ test.cpp -o test -lgtest && ./test
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_NEAR
[       OK ] EXPTEST.EXPTEST_NEAR (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

如果将第三个参数的误差改为0.001,则无法通过测试。

❯ g++ test.cpp -o test -lgtest && ./test
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from EXPTEST
[ RUN      ] EXPTEST.EXPTEST_NEAR
test.cpp:8: Failure
The difference between 3.14 and 3.15 is 0.0099999999999997868, which exceeds 0.001, where
3.14 evaluates to 3.1400000000000001,
3.15 evaluates to 3.1499999999999999, and
0.001 evaluates to 0.001.

[  FAILED  ] EXPTEST.EXPTEST_NEAR (0 ms)
[----------] 1 test from EXPTEST (0 ms total)

[----------] Global test environment tear-down