本文首发于 ❄️慕雪的寒舍
gtest模块的安装参考站内教程 ubuntu安装google gtest
本文使用的gtest版本为1.14.0;
1.gtest是用来干嘛的?
google gtest是一个c++的单元测试模块,它提供了一系列规范化的宏,来帮助我们进行函数的单元测试。
单元测试你可以理解为测试我们编写好的每个函数模块,确保这些函数的功能不会影响其他函数,并保证函数能依照预期的功能进行工作。
要知道,绝大部分的软件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 asContainsRegex(s)
, notEq(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