当前位置:   article > 正文

GoogleTest之断言_assert_eq

assert_eq

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5

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

普通断言

EXPECT_THAT

EXPECT_THAT(value,matcher)  
ASSERT_THAT(value,matcher)
  • 1
  • 2

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

示例

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

布尔条件断言

EXPECT_TRUE

EXPECT_TRUE(condition)
ASSERT_TRUE(condition)
  • 1
  • 2

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

EXPECT_FALSE

EXPECT_FALSE(condition)
ASSERT_FALSE(condition)
  • 1
  • 2

验证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)
  • 1
  • 2

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

EXPECT_NE

EXPECT_NE(val1,val2)
ASSERT_NE(val1,val2)
  • 1
  • 2

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

EXPECT_LT

EXPECT_LT(val1,val2)
ASSERT_LT(val1,val2)
  • 1
  • 2

验证 val1<val2.

EXPECT_LE

EXPECT_LE(val1,val2)
ASSERT_LE(val1,val2)
  • 1
  • 2

验证 val1<=val2.

EXPECT_GT

EXPECT_GT(val1,val2)
ASSERT_GT(val1,val2)
  • 1
  • 2

验证 val1>val2.

EXPECT_GE

EXPECT_GE(val1,val2)
ASSERT_GE(val1,val2)
  • 1
  • 2

验证 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)
  • 1
  • 2

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

EXPECT_STRNE

EXPECT_STRNE(str1,str2)
ASSERT_STRNE(str1,str2)
  • 1
  • 2

比较str1和str2是否不同

EXPECT_STRCASEEQ

EXPECT_STRCASEEQ(str1,str2)
ASSERT_STRCASEEQ(str1,str2)
  • 1
  • 2

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

EXPECT_STRCASENE

EXPECT_STRCASENE(str1,str2)
ASSERT_STRCASENE(str1,str2)
  • 1
  • 2

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

浮点型比较

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

EXPECT_FLOAT_EQ

EXPECT_FLOAT_EQ(val1,val2)
ASSERT_FLOAT_EQ(val1,val2)
  • 1
  • 2

比较float类型,保留后四位

EXPECT_DOUBLE_EQ

EXPECT_DOUBLE_EQ(val1,val2)
ASSERT_DOUBLE_EQ(val1,val2)
  • 1
  • 2

比较double类型,保留后四位

EXPECT_NEAR

EXPECT_NEAR(val1,val2,abs_error)
ASSERT_NEAR(val1,val2,abs_error)
  • 1
  • 2

比较两个值的误差的绝对值是否超过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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

显式成功与失败

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

switch(expression) {
  case 1:
      ADD_FAILURE() << "..";
  case 2:
      ....
  default:
      FATAL() << "We shouldn't get here.";
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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---------";
}
  • 1
  • 2
  • 3
  • 4
  • 5

输出如下:
在这里插入图片描述
结果证明,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)
  • 1
  • 2

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

EXPECT_ANY_THROW

EXPECT_ANY_THROW(statement)
ASSERT_ANY_THROW(statement)
  • 1
  • 2

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

EXPECT_NO_THROW

EXPECT_NO_THROW(statement)
ASSERT_NO_THROW(statement)
  • 1
  • 2

验证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_;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

异常调用函数:

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

void test_exception() {
    try {
        throw MyException {"hello"};
    }
    catch(const MyException& e) {
        std::cerr << "e.what()" << '\n';
    } 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

断言:

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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

谓词断言

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

将给定的参数传给谓词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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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

注意:如果谓词是重载函数或者模板函数,断言宏可能无法识别,需要显式指定函数参数类型
重载函数:
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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

模板函数作为谓词,注意在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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

EXPECT_PRED1不需要括号

template <typename T>
bool IsNegative(T x) {
  return x < 0;
}
TEST(AssertionTest4, pred_test0) {
  EXPECT_PRED1(IsNegative<int>, 1);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

谓词签名如下:

testing::AssertionResult PredicateFormatter(const char* expr1,
                                            const char* expr2,
                                            ...
                                            const char* exprn,
                                            T1 val1,
                                            T2 val2,
                                            ...
                                            Tn valn);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

目测通过这个方式可以输出像输出的任何信息。
使用返回类型为::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();

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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)
  • 1
  • 2

验证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()");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

EXPECT_DEATH_IF_SUPPORTED

EXPECT_DEATH_IF_SUPPORTED(statement,matcher)
ASSERT_DEATH_IF_SUPPORTED(statement,matcher)
  • 1
  • 2

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

EXPECT_DEBUG_DEATH

EXPECT_DEBUG_DEATH(statement,matcher)
ASSERT_DEBUG_DEATH(statement,matcher)
  • 1
  • 2

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

EXPECT_EXIT

EXPECT_EXIT(statement,predicate,matcher)
ASSERT_EXIT(statement,predicate,matcher)
  • 1
  • 2

验证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);
  • 1
  • 2
  • 3
  • 4
  • 5

退出状态示例:

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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

退出信号示例:

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");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

死亡测试形式

一般有两种形式,“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:
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

类型断言

::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");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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

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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/242340
推荐阅读
相关标签
  

闽ICP备14008679号