白天是个程序员,晚上就是个有抱负的演员,这是就是我,我住在天朝的陪都。

googletest(GTest)

include <gtest/gtest.h>

/*

GTest中断言都是成对出现的。即分为两个系列:

1. ASSERT_*系列    
2 .EXPECT_*系列

EXPECT_*系列是比较常用的。
在一个测试特例中,如果局部测试使用了EXPECT_*系列函数,
它将保证本次局部测试结果不会影响之后的流程。但是ASSERT_*
系列在出错的情况下,当前测试特例中剩下的流程就不走了。
他们的区别就是在是出错时调用了GTEST_NONFATAL_FAILURE_还是GTEST_FATAL_FAILURE_
在出错的情况下,ASSERT_*的else里return了。而EXPECT_*的else没有return。


二进制比较断言
ASSERT_EQ(val1,val2);    EXPECT_EQ(val1,val2);    val1 == val2    equal
ASSERT_NE(val1,val2);    EXPECT_NE(val1,val2);    val1 != val2    not equal
ASSERT_LT(val1,val2);    EXPECT_LT(val1,val2);    val1 < val2    less than
ASSERT_LE(val1,val2);    EXPECT_LE(val1,val2);    val1 <= val2    less equal
ASSERT_GT(val1,val2);    EXPECT_GT(val1,val2);    val1 > val2    big than
ASSERT_GE(val1,val2);    EXPECT_GE(val1,val2);    val1 >= val2    big equal

一般来说二进制比较,都是对比其结构体所在内存的内容。
C++大部分原生类型都是可以使用二进制对比的。
但是对于自定义类型,我们就要定义一些操作符的行为,
比如=、<等,我这儿就不举例了。


字符串对比断言
ASSERT_STREQ(str1,str2);    EXPECT_STREQ(str1,_str_2);    the two C strings have the same content    string equal
ASSERT_STRNE(str1,str2);    EXPECT_STRNE(str1,str2);    the two C strings have different content    string not equal
ASSERT_STRCASEEQ(str1,str2);    EXPECT_STRCASEEQ(str1,str2);    the two C strings have the same content, ignoring case    string (ignoring) case equal
ASSERT_STRCASENE(str1,str2);    EXPECT_STRCASENE(str1,str2);    the two C strings have different content, ignoring case    string (ignoring) case not euqal


浮点对比断言
ASSERT_FLOAT_EQ(val1, val2);    EXPECT_FLOAT_EQ(val1, val2);    the two float values are almost equal
ASSERT_DOUBLE_EQ(val1, val2);    EXPECT_DOUBLE_EQ(val1, val2);    the two double values are almost equal

almost euqal表示两个数只是近似相似,
默认的是是指两者的差值在4ULP之内(Units in the Last Place)。
我们还可以自己制定精度
ASSERT_NEAR(val1, val2, abs_error);    EXPECT_NEAR(val1, val2, abs_error);    the difference between val1 and val2 doesn't exceed the given absolute error

ASSERT_NEAR(-1.0f, -1.1f, 0.2f);
ASSERT_NEAR(2.0f, 3.0f, 1.0f);

对于浮点数的比较,感兴趣的同学可以查看下GTest的源码,还是有点意思的。



成功失败断言
该类断言用于直接标记是否成功或者失败。
可以使用SUCCEED()宏标记成功,
使用FAIL()宏标记致命错误(同ASSERT_*),
ADD_FAILURE()宏标记非致命错误(同EXPECT_*)
if (Check) {
    SUCCEED();
}
else {
    FAIL();
}
我们直接在自己的判断下设置断言。
这儿有个地方需要说一下,
SUCCEED()宏会调用GTEST_MESSAGE_AT_宏,
从而会影响TestResult的test_part_results结构体,
这也是唯一的成功情况下影响该结构体的地方


类型对比断言
该类断言只有一个::testing::StaticAssertTypeEq<T, T>()。
当类型相同时,它不会执行任何内容。
如果不同则会引起编译错误。
但是需要注意的是,要使代码触发编译器推导类型,
否则也会发生编译错误。如
template <typename T> class Foo {
 public:
  void Bar() { ::testing::StaticAssertTypeEq<int, T>(); }
};
如下的代码就不会引起编译冲突    
void Test1() { Foo<bool> foo; }
但是下面的代码由于引发了编译器的类型推导,所以会触发编译错误
void Test2() { Foo<bool> foo; foo.Bar(); }


异常断言
常断言是在断言中接收一定类型的异常,并转换成断言形式。它有如下几种
ASSERT_THROW(statement, exception_type);    EXPECT_THROW(statement, exception_type);    statement throws an exception of the given type
ASSERT_ANY_THROW(statement);    EXPECT_ANY_THROW(statement);    statement throws an exception of any type
ASSERT_NO_THROW(statement);    EXPECT_NO_THROW(statement);    statement doesn't throw any exception


参数名输出断言
ASSERT_PRED1(pred1, val1);    EXPECT_PRED1(pred1, val1);    pred1(val1) returns true
ASSERT_PRED2(pred2, val1, val2);    EXPECT_PRED2(pred2, val1, val2);    pred2(val1, val2) returns true
...    ...    ...
目前版本的GTest支持5个参数的版本ASSERT/EXPECT_PRED5宏。其使用方法是

template <typename T1, typename T2>
bool GreaterThan(T1 x1, T2 x2) {
  return x1 > x2;
}

TEST(PredicateAssertionTest, AcceptsTemplateFunction) {
  int a = 5;
  int b = 6;
  ASSERT_PRED2((GreaterThan<int, int>), a, b);
}
其输出是
error: (GreaterThan<int, int>)(a, b) evaluates to false, where
a evaluates to 5
b evaluates to 6


子过程中使用断言
如果子过程中使用了断言,
则结果输出只会指向子过程,
而不会指向父过程中的某个调用。
为了便于阅读我们可以使用SCOPED_TRACE宏去标记下位置
void Sub(int n) {
    ASSERT_EQ(1, n);
}
 
TEST(SubTest, Test1) {
    {
        SCOPED_TRACE("A");
        Sub(2);
    }
    Sub(3);
}
其结果输出时标记了下A这行位置,
可见如果没有这个标记,
是很难区分出是哪个Sub失败的。

..\test\gtest_unittest.cc(87): error:       Expected: 1
To be equal to: n
      Which is: 2
Google Test trace:
..\test\gtest_unittest.cc(92): A
..\test\gtest_unittest.cc(87): error:       Expected: 1
To be equal to: n
      Which is: 3
我们再注意下Sub的实现,其使用了ASSERT_EQ断言,该断言并不会影响Test1测试特例的运行,其原因我们在之前做过分析了。为了消除这种可能存在的误解,GTest推荐使用在子过程中使用ASSERT/EXPECT_NO_FATAL_FAILURE(statement);

    如果父过程一定要在子过程发生错误时退出怎么办?

我们可以使用::testing::Test::HasFatalFailure()去判断当前线程中是否产生过错误。

TEST(SubTest, Test1) {
    {
        SCOPED_TRACE("A");
        Sub(2);
    }
    if (::testing::Test::HasFatalFailure())
        return;
    Sub(3);
}
      
gtest提供的TEST方式我不会用,因为多个TEST不能共享同一份数据
TEST_F是一个宏,TEST_F(classname, casename){}在函数体内去做具体的验证。
用gtest,首先要声明一个类,继承自gtest里的Test类:

*/

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

添加新评论

咻~