GoogleTest之断言

gtest中assert的头文件: gtest/gtest.h
EXPECT_ASSERT_两种形式,EXPECT_产生非致命错误,ASSERT_产生致命错误并中断当前函数;所有断言宏支持使用重载<<的流输出

ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";

for (int i = 0; i < x.size(); ++i) {
  EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
}

对断言FAIL*ASSERT*的一个限制是,只能用在返回类型为void的函数中(如果是非void返回类型编译不通过)。所以对于返回类型为非void的函数,可以用参数代替。

普通断言

EXPECT_THAT

EXPECT_THAT(value,matcher)  
ASSERT_THAT(value,matcher)

验证value是否和matcher匹配,matcher参考这里

示例

EXPECT_THAT("HelloWorld", ::testing::StartsWith("Hello"));  // 验证字符串HelloWorld是否以Hello开头

布尔条件断言

EXPECT_TRUE

EXPECT_TRUE(condition)
ASSERT_TRUE(condition)

验证condition是否为true,true为通过

EXPECT_FALSE

EXPECT_FALSE(condition)
ASSERT_FALSE(condition)

验证condition是否为false

二进制比较

用来比较两个值,参数中的两个值必须是可以比较的(支持比较运算符)
如果一个参数支持<<操作符,当比较失败时会被调用打印参数,否则gtest会用它认为最好的方式打印,具体参考https://google.github.io/googletest/advanced.html#teaching-googletest-how-to-print-your-values
支持宽字符(wstring)和窄字符(string)
浮点型数据不能比较

EXPECT_EQ

EXPECT_EQ(val1,val2)
ASSERT_EQ(val1,val2)

验证val1==val2,不相等则出错。如果比较两个C风格数组,比较的是两个数组的地址而不是数组值。比较字符串使用EXPECT_STREQ。比较指针使用EXPECT_EQ(ptr, nullptr)而不是EXPECT_EQ(ptr, NULL)

EXPECT_NE

EXPECT_NE(val1,val2)
ASSERT_NE(val1,val2)

验证val1 != val2。同样,如果是指针比较,对比的是内存中的地址值,而不是是否有相同的值。
比较指针则使用EXPECT_NE(ptr, nullptr)代替EXPECT_NE(ptr, NULL)

EXPECT_LT

EXPECT_LT(val1,val2)
ASSERT_LT(val1,val2)

验证 val1<val2.

EXPECT_LE

EXPECT_LE(val1,val2)
ASSERT_LE(val1,val2)

验证 val1<=val2.

EXPECT_GT

EXPECT_GT(val1,val2)
ASSERT_GT(val1,val2)

验证 val1>val2.

EXPECT_GE

EXPECT_GE(val1,val2)
ASSERT_GE(val1,val2)

验证 val1>=val2.

字符串比较

这里的字符串比较用于两个C风格的字符串,如果对比两个string对象,使用 EXPECT_EQ或者EXPECT_NE
如果要将C数组和NULL做对比, 使用EXPECT_EQ(c_string, nullptr)或者EXPECT_NE(c_string, nullptr).

EXPECT_STREQ

EXPECT_STREQ(str1,str2)
ASSERT_STREQ(str1,str2)

比较str1和str2是否有相同的值

EXPECT_STRNE

EXPECT_STRNE(str1,str2)
ASSERT_STRNE(str1,str2)

比较str1和str2是否不同

EXPECT_STRCASEEQ

EXPECT_STRCASEEQ(str1,str2)
ASSERT_STRCASEEQ(str1,str2)

忽略大小写比较str1和str2是否有相同的值

EXPECT_STRCASENE

EXPECT_STRCASENE(str1,str2)
ASSERT_STRCASENE(str1,str2)

忽略大小写比较str1和str2是否有不同的值

浮点型比较

浮点型由于精度舍入原因,使用EXPECT_EQ 并不能很准确判断,Google test提供了专用于比较浮点型比较的断言。

EXPECT_FLOAT_EQ

EXPECT_FLOAT_EQ(val1,val2)
ASSERT_FLOAT_EQ(val1,val2)

比较float类型,保留后四位

EXPECT_DOUBLE_EQ

EXPECT_DOUBLE_EQ(val1,val2)
ASSERT_DOUBLE_EQ(val1,val2)

比较double类型,保留后四位

EXPECT_NEAR

EXPECT_NEAR(val1,val2,abs_error)
ASSERT_NEAR(val1,val2,abs_error)

比较两个值的误差的绝对值是否超过abs_error

TEST(TestFloatCase, float_case01) {
    float a = 2.34732, b = 2.34732;
    double c = 6.75433, d = 9.634638;
    EXPECT_FLOAT_EQ(a, b);   // success
    EXPECT_DOUBLE_EQ(c, d);  // fail
    EXPECT_NEAR(a, c, 5);    // success
    EXPECT_NEAR(c, a, -5);   // fail
}

显式成功与失败

这种是直接生成成功和失败,代替了表达式或者值。常用在控制流,而不是需要判断boolean的表达式来决定test的成功和失败,举例如下

switch(expression) {
  case 1:
      ADD_FAILURE() << "..";
  case 2:
      ....
  default:
      FATAL() << "We shouldn't get here.";

SUCCEED

SUCCEED()生成一个success,不会有用户可见的输出,后续有可能会有输出

FAIL

FAIL()生成一个fatal failure,从当前函数退出,不会执行后面的代码,只能用在返回值为void的函数中。

ADD_FAILURE

ADD_FAILURE()生成一个nonfatal failure,它会允许当前函数继续执行,这是与FAIL的区别

ADD_FAILURE_AT

ADD_FAILURE_AT(file_path,line_number) 在一个文件的指定行生成一条nonfatal failure

void test_func1() {
    SUCCEED() << "------------gtest SUCCEED------------";
    ADD_FAILURE() << "----------gtest ADD_FAILURE--------------";
    ADD_FAILURE_AT("/home//iLearning/code/gtest/gtest_project/src/doc.txt", 2) << "--------gtest ADD_FAILURE_AT---------";
}

输出如下:
在这里插入图片描述
结果证明,SUCCEED()没有输出任何信息,ADD_FAILURE()和ADD_FAILURE_AT(file_path,line_number) 都有failure的输出。

  • 但ADD_FAILURE_AT并没有在一个文件的指定行生成一条nonfatal failure(不管这个文件在测试程序运行前是否存在)

异常断言

验证是否会抛出异常

EXPECT_THROW

EXPECT_THROW(statement,exception_type)
ASSERT_THROW(statement,exception_type)

验证statement会抛出类型为exception_type的异常

EXPECT_ANY_THROW

EXPECT_ANY_THROW(statement)
ASSERT_ANY_THROW(statement)

验证statement会抛出任何类型的异常

EXPECT_NO_THROW

EXPECT_NO_THROW(statement)
ASSERT_NO_THROW(statement)

验证statement不会抛出异常

定义异常类:

class MyException : public std::exception {
public:
  MyException(string_view str): str_(str) {}

  const char* what() const _GLIBCXX_NOTHROW override {
      return str_.c_str();
  }
private:
  std::string str_;
};

异常调用函数:

void test_exception_func0() {
    throw MyException {"hello"};
}

void test_exception() {
    try {
        throw MyException {"hello"};
    }
    catch(const MyException& e) {
        std::cerr << "e.what()" << '\n';
    } 
}

断言:

TEST(Exception_TestSuite, test00) {
    EXPECT_THROW(test_exception_func0, MyException);
}

TEST(Exception_TestSuite, test01) {
    EXPECT_ANY_THROW(test_exception_func0);
}

TEST(Exception_TestSuite, test02) {
    EXPECT_NO_THROW(test_exception_func0);
}

谓词断言

EXPECT_PRED*

EXPECT_PRED1(pred,val1)
EXPECT_PRED2(pred,val1,val2)
EXPECT_PRED3(pred,val1,val2,val3)
EXPECT_PRED4(pred,val1,val2,val3,val4)
EXPECT_PRED5(pred,val1,val2,val3,val4,val5)

ASSERT_PRED1(pred,val1)
ASSERT_PRED2(pred,val1,val2)
ASSERT_PRED3(pred,val1,val2,val3)
ASSERT_PRED4(pred,val1,val2,val3,val4)
ASSERT_PRED5(pred,val1,val2,val3,val4,val5)

将给定的参数传给谓词pred,如果pred返回true则断言成功,否则失败,如果失败了,它会打印每个参数值。pred是一个函数或者函数对象,可以接受在断言宏中给定的其他参数。

bool MutuallyPrime(int i, int j) {
    return i > j;
}
const int a = 2;
const int b = 3;
const int c = 4;
TEST(TestPredSuite, pred_test) {
    EXPECT_PRED2(MutuallyPrime, b, a);
    EXPECT_PRED2(MutuallyPrime, c, b);
}

输出如下:在这里插入图片描述

注意:如果谓词是重载函数或者模板函数,断言宏可能无法识别,需要显式指定函数参数类型
重载函数:
MutuallyPrime重载,注意EXPECT_PRED*中指定函数的写法

bool MutuallyPrime(int i, int j) {
    return i > j;
}
bool MutuallyPrime(char i, int j) {
    return i > j;
} 
const int a = 2;
const int b = 3;
const int c = 4;
const char d = 5;
TEST(TestPredSuite, pred_test) {
    EXPECT_PRED2(static_cast<bool(*)(char, int)>(MutuallyPrime), d, a);
    EXPECT_PRED2(static_cast<bool(*)(int, int)>(MutuallyPrime), c, b);
}

模板函数作为谓词,注意在EXPECT_PRED2中第一个参数需要用括号:

const int a = 2;
const int b = 3;
const int c = 4;
const char d = 5;
template<typename T1, typename T2>
bool CompareVal(T1 t1, T2 t2) {
    return t1 > t2;
}
TEST(TestPredSuite, pred_test) {
    EXPECT_PRED2((CompareVal<char, int>), d, a);
    EXPECT_PRED2((CompareVal<int, int>), c, b);
}

EXPECT_PRED1不需要括号

template <typename T>
bool IsNegative(T x) {
  return x < 0;
}
TEST(AssertionTest4, pred_test0) {
  EXPECT_PRED1(IsNegative<int>, 1);
}

EXPECT_PRED_FORMAT*

EXPECT_PRED_FORMAT1(pred_formatter,val1)
EXPECT_PRED_FORMAT2(pred_formatter,val1,val2)
EXPECT_PRED_FORMAT3(pred_formatter,val1,val2,val3)
EXPECT_PRED_FORMAT4(pred_formatter,val1,val2,val3,val4)
EXPECT_PRED_FORMAT5(pred_formatter,val1,val2,val3,val4,val5)

ASSERT_PRED_FORMAT1(pred_formatter,val1)
ASSERT_PRED_FORMAT2(pred_formatter,val1,val2)
ASSERT_PRED_FORMAT3(pred_formatter,val1,val2,val3)
ASSERT_PRED_FORMAT4(pred_formatter,val1,val2,val3,val4)
ASSERT_PRED_FORMAT5(pred_formatter,val1,val2,val3,val4,val5)

谓词签名如下:

testing::AssertionResult PredicateFormatter(const char* expr1,
                                            const char* expr2,
                                            ...
                                            const char* exprn,
                                            T1 val1,
                                            T2 val2,
                                            ...
                                            Tn valn);

目测通过这个方式可以输出像输出的任何信息。
使用返回类型为::test::AssertionResult的函数:

namespace testing {

// Returns an AssertionResult object to indicate that an assertion has
// succeeded.
AssertionResult AssertionSuccess();

// Returns an AssertionResult object to indicate that an assertion has
// failed.
AssertionResult AssertionFailure();

}

AssertionResult 对象可以使用 << 运算符输出信息。
为了在boolear断言中,输出更加可读的信息,可以使用返回AssertionResult代替bool的predicate函数:

死亡断言

任何测试导致进程以一种期望的方式终止叫做死亡测试。注意抛出异常不能称为死亡测试,因为调用部分可以捕获到。
死亡断言会生成新的子进程,并在子进程中执行代码,具体会做些什么依赖平台和变量::testing::GTEST_FLAG(death_test_style), 这个变量由命令行flag --gtest_death_test_style初始化:

  • 在POSIX系统, fork() (or clone() on Linux) 被用来生成子进程,然后:
    • 如果变量值为"fast", 死亡测试被立即执行
    • 如果变量值为 “threadsafe”, the child process re-executes the unit test binary just as it was originally invoked, but with some extra flags to cause just the single death test under consideration to be run.
  • 在Windows上子进程由CreateProcess() 创建, and re-executes the binary to cause just the single death test under consideration to be run,就像POSIX上的"threadsafe"模式
    其他值是非法的,会引起死亡测试的失败,默认值是“fast”。
    死亡测试关注以下两点:
  • statement 是否abort或退出进程?
  • 在使用宏ASSERT_EXIT 和 EXPECT_EXIT的情况下,exit status是否满足predicate,标准错误输出是否满足matcher?

EXPECT_DEATH

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

验证statement 以非0的状态离开并退出进程,并且stderr输出信息匹配matcher。matcher 既可以是一个const std::string&的matcher 对象,也可以是一个正则表达式:一个字符串s被认为是 ContainsRegex(s),而不是Eq(s)。
示例:

void DoSomething(int* n) {
  std::cerr << "Error on line .sss of DoSomething()";  // 注意:要用stderr输出,类似std::cout的输出都会导致验证失败
  abort();
}

TEST(AssertionTest5, death_test00) {
  EXPECT_DEATH({
    int n = 5;
    DoSomething(&n);
  }, "Error on line .* of DoSomething()");
}

EXPECT_DEATH_IF_SUPPORTED

EXPECT_DEATH_IF_SUPPORTED(statement,matcher)
ASSERT_DEATH_IF_SUPPORTED(statement,matcher)

如果支持death test则和EXPECT_DEATH一样,否则什么都不做。

EXPECT_DEBUG_DEATH

EXPECT_DEBUG_DEATH(statement,matcher)
ASSERT_DEBUG_DEATH(statement,matcher)

在debug模式下和EXPECT_DEATH一样,非debug模式下(i.e. NDEBUG is defined), 只执行statement.

EXPECT_EXIT

EXPECT_EXIT(statement,predicate,matcher)
ASSERT_EXIT(statement,predicate,matcher)

验证statement用一个符合predicate的int类型的exit status引起进程终止, 并产生匹配matcher的stderr标准错误输出信息。谓词predicate 是一个 function or functor接受一个int类型的exit status参数,并返回一个bool类型。 GoogleTest提供两个predicate用于处理常见的情形:

// 进程退出状态如果等于exit_code则返回true
::testing::ExitedWithCode(exit_code);

// 杀死进程的信号为signal_number则返回true,windows下不可用
::testing::KilledBySignal(signal_number);

退出状态示例:

void NormalExit() {
  std::cerr << "hi,I am happy";
  _exit(1);
}

TEST(AssertionTest6, death_test01) {
  EXPECT_EXIT(NormalExit(), testing::ExitedWithCode(1), "hi,I am happy");  // matcher和exit code任一不符合会导致测试fail
}

退出信号示例:

void KillProcess() {
  std::cerr << "I am not happy" << std::endl;
  abort();
}

TEST(MyDeathTest, KillProcess) {
  EXPECT_EXIT(KillProcess(), testing::KilledBySignal(SIGABRT), // matcher和退出信号任一不一致会导致测试fail
              "I am not happy");
}

死亡测试形式

一般有两种形式,“fast"和“threadsafe”。默认为fast。threadsafe会保证在线程安全的 场景下进行测试。可以通过GTEST_FLAG_SET(death_test_style, "threadsafe");来设置。
可以在main中为每个死亡测试设置,或单独为某个测试设置。

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

TEST(MyDeathTest, TestOne) {
  GTEST_FLAG_SET(death_test_style, "threadsafe");
  ASSERT_DEATH(ThisShouldDie(), "");  // This test is run in the "threadsafe" style:
}

TEST(MyDeathTest, TestTwo) {
  ASSERT_DEATH(ThisShouldDie(), "");  // This test is run in the "fast" style:
}

类型断言

::testing::StaticAssertTypeEq<T1, T2>(); 判断类型T1和T2是否相同。如果不同编译会报错,如果相同不会有任何操作。这在模板代码中非常有用。

template<typename T1, typename T2>
class TemTest {
public:
  TemTest(const T1& t1, const T2& t2) {
      ::testing::StaticAssertTypeEq<T1, T2>();
  }
};

void test {
  TemTest<int, string> t(1, "good");
}

编译报错:在这里插入图片描述
注意,这个是在编译阶段判断的,如果是在模板类的成员函数等没有在编译阶段具现化则不会报错。如下例所示,不会出现类型不同的报错。

template<typename T1, typename T2> class TemTest {
public:
  TemTest(const T1& t1, const T2& t2) {
      std::cout << "t1: " << t1 << ", t2: " << t2 << std::endl;
  }
  void Bar() {
      ::testing::StaticAssertTypeEq<T1, T2>();
  }
};

void test {
  TemTest<int, string> t(1, "good");
}
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值