assert断言 - googletest(二)

本文详述了谷歌测试库gtest中的断言宏,包括ASSERT系列和EXPECT系列的使用,如ASSERT_EQ、EXPECT_TRUE等,以及它们在失败时的行为。此外,还介绍了对浮点数、异常、类型检查和自定义消息输出的断言方式,帮助开发者更好地理解和使用gtest进行单元测试。
摘要由CSDN通过智能技术生成

这篇文章主要总结gtest中的所有断言相关的宏。 gtest中,断言的宏可以理解为分为两类,一类是ASSERT系列,一类是EXPECT系列。一个直观的解释就是:

  • 1. ASSERT_* 系列的断言,当检查点失败时,退出当前函数(注意:并非退出当前案例)。
  • 2. EXPECT_* 系列的断言,当检查点失败时,继续往下执行。

1. 断言实例

// int型比较,预期值:3,实际值:Add(1, 2)
EXPECT_EQ(3, Add(1, 2))

断言除数结果可以是直接在终端打印,也可以生成xml报告文件,同时也可以在测试结果中通过<<追加新的内容。如上测试结果不同格式下的内容输出

假如你的Add(1, 2) 结果为4的话,会在结果中输出:
g:\myproject\c++\gtestdemo\gtestdemo\gtestdemo.cpp(16): error: Value of: Add(1, 2)
  Actual: 4
Expected:3
如果是输出到xml文件中
<testcase name="Demo" status="run" time="0" classname="AddTest">
      <failure message="Value of: Add(1, 2)   Actual: 4 Expected: 3" type=""><![CDATA[g:\myproject\c++\gtestdemo\gtestdemo\gtestdemo.cpp:16
Value of: Add(1, 2)
  Actual: 4
Expected: 3]]></failure>
</testcase>

如果你对自动输出的出错信息不满意的话,你还可以通过操作符<<将一些自定义的信息输出,通常,这对于调试或是对一些检查点的补充说明来说,非常有用!

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

从输出结果中就可以定位到在 i = 2 时出现了错误。这样的输出结果看起来更加有用,容易理解: 
g:\myproject\c++\gtestdemo\gtestdemo\gtestdemo.cpp(25): error: Value of: y[i]
  Actual: 4
Expected: x[i]
Which is: 3
Vectors x and y differ at index 2

2. 断言检查总结

2.1 布尔值检查

Fatal assertionNonfatal assertionVerifies
ASSERT_TRUE(condition);EXPECT_TRUE(condition);condition is true
ASSERT_FALSE(condition);EXPECT_FALSE(condition);condition is false

2.2 数值型数据检查

Fatal assertionNonfatal assertionVerifies
ASSERT_EQ(expectedactual);EXPECT_EQ(expectedactual);expected == actual
ASSERT_NE(val1val2);EXPECT_NE(val1val2);val1 != val2
ASSERT_LT(val1val2);EXPECT_LT(val1val2);val1 < val2
ASSERT_LE(val1val2);EXPECT_LE(val1val2);val1 <= val2
ASSERT_GT(val1val2);EXPECT_GT(val1val2);val1 > val2
ASSERT_GE(val1val2);EXPECT_GE(val1val2);val1 >= val2

2.3 字符串检查

Fatal assertionNonfatal assertionVerifies
ASSERT_STREQ(expected_stractual_str);EXPECT_STREQ(expected_stractual_str);the two C strings have the same content
ASSERT_STRNE(str1str2);EXPECT_STRNE(str1str2);the two C strings have different content
ASSERT_STRCASEEQ(expected_stractual_str);EXPECT_STRCASEEQ(expected_stractual_str);the two C strings have the same content, ignoring case
ASSERT_STRCASENE(str1str2);EXPECT_STRCASENE(str1str2);the two C strings have different content, ignoring case

*STREQ*和*STRNE*同时支持char*和wchar_t*类型的,*STRCASEEQ*和*STRCASENE*却只接收char*,估计是不常用吧。下面是几个例子:

TEST(StringCmpTest, Demo)
{
    char* pszCoderZh = "CoderZh";
    wchar_t* wszCoderZh = L"CoderZh";
    std::string strCoderZh = "CoderZh";
    std::wstring wstrCoderZh = L"CoderZh";

    EXPECT_STREQ("CoderZh", pszCoderZh);
    EXPECT_STREQ(L"CoderZh", wszCoderZh);

    EXPECT_STRNE("CnBlogs", pszCoderZh);
    EXPECT_STRNE(L"CnBlogs", wszCoderZh);

    EXPECT_STRCASEEQ("coderzh", pszCoderZh);
    //EXPECT_STRCASEEQ(L"coderzh", wszCoderZh);    不支持

    EXPECT_STREQ("CoderZh", strCoderZh.c_str());
    EXPECT_STREQ(L"CoderZh", wstrCoderZh.c_str());
}

2.4 显示返回成功或失败

直接返回成功:SUCCEED(); 返回失败:

Fatal assertionNonfatal assertion
FAIL();ADD_FAILURE();
TEST(ExplicitTest, Demo)
{
    ADD_FAILURE() << "Sorry"; // None Fatal Asserton,继续往下执行。
    //FAIL(); // Fatal Assertion,不往下执行该案例。
    SUCCEED();
}

2.5 异常检查

Fatal assertionNonfatal assertionVerifies
ASSERT_THROW(statementexception_type);EXPECT_THROW(statementexception_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
int Foo(int a, int b)
{
    if (a == 0 || b == 0)
    {
        throw "don't do that";
    }
    int c = a % b;
    if (c == 0)
        return b;
    return Foo(b, c);
}

TEST(FooTest, HandleZeroInput)
{
    EXPECT_ANY_THROW(Foo(10, 0));
    EXPECT_THROW(Foo(0, 5), char*);
}

2.6 Predicate Assertions

在使用EXPECT_TRUE或ASSERT_TRUE时,有时希望能够输出更加详细的信息,比如检查一个函数的返回值TRUE还是FALSE时,希望能够输出传入的参数是什么,以便失败后好跟踪。因此提供了如下的断言:

Fatal assertionNonfatal assertionVerifies
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
.........

在上面,predn是一个n元谓词函数或函子,其中val1,val2,...和valn是它的参数。 如果谓词在应用于给定参数时返回true,则断言成功,否则失败。 当断言失败时,它打印每个参数的值。 在任何一种情况下,参数只计算一次。Google人说了,他们只提供<=5个参数的,如果需要测试更多的参数,直接告诉他们。下面看看这个东西怎么用。

bool MutuallyPrime(int m, int n)
{
    return Foo(m , n) > 1;
}

TEST(PredicateAssertionTest, Demo)
{
    int m = 5, n = 6;
    EXPECT_PRED2(MutuallyPrime, m, n);
}

当失败时,返回错误信息:

error: MutuallyPrime(m, n) evaluates to false, where
m evaluates to 5
n evaluates to 6

注意:

 1. 如果在使用ASSERT_PRED *或EXPECT_PRED *时看到编译器错误“no matching function to call(无匹配函数调用)”,请参阅此常见问题解答 this FAQ 以了解如何解决它。
 2. 目前我们只提供arity <= 5的谓词断言。如果你需要更高级的断言,让我们知道。

如果你发现由(ASSERT | EXPECT)_PRED *和(ASSERT | EXPECT)_(TRUE | FALSE)生成的默认消息不令人满意,或者您的谓词的某些参数不支持流到ostream,您可以使用以下谓词 - 格式化程序断言 以完全自定义消息的格式化:

Fatal assertionNonfatal assertionVerifies
ASSERT_PRED_FORMAT1(pred_format1, val1);`EXPECT_PRED_FORMAT1(pred_format1, val1);pred_format1(val1) is successful
ASSERT_PRED_FORMAT2(pred_format2, val1, val2);EXPECT_PRED_FORMAT2(pred_format2, val1, val2);pred_format2(val1, val2) is successful
......
testing::AssertionResult AssertFoo(const char* m_expr, const char* n_expr, const char* k_expr, int m, int n, int k) {
    if (Foo(m, n) == k)
        return testing::AssertionSuccess();
    testing::Message msg;
    msg << m_expr << " 和 " << n_expr << " 的最大公约数应该是:" << Foo(m, n) << " 而不是:" << k_expr;
    return testing::AssertionFailure(msg);
}

TEST(AssertFooTest, HandleFail)
{
    EXPECT_PRED_FORMAT3(AssertFoo, 3, 6, 2);
}

失败时,输出信息:error: 3 和 6 的最大公约数应该是:3 而不是:2

2.7 浮点型检查

Fatal assertionNonfatal assertionVerifies
ASSERT_FLOAT_EQ(expected, actual);EXPECT_FLOAT_EQ(expected, actual);the two float values are almost equal
ASSERT_DOUBLE_EQ(expected, actual);EXPECT_DOUBLE_EQ(expected, actual);the two double values are almost equal

对相近的两个数比较:

Fatal assertionNonfatal assertionVerifies
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

同时,还可以使用:

EXPECT_PRED_FORMAT2(testing::FloatLE, val1, val2);
EXPECT_PRED_FORMAT2(testing::DoubleLE, val1, val2);

2.8 Windows HRESULT assertions

Fatal assertionNonfatal assertionVerifies
ASSERT_HRESULT_SUCCEEDED(expression);EXPECT_HRESULT_SUCCEEDED(expression);expression is a success HRESULT
ASSERT_HRESULT_FAILED(expression);EXPECT_HRESULT_FAILED(expression);expression is a failure HRESULT

生成的输出包含与expression返回的HRESULT代码相关联的人工可读错误消息。 

CComPtr shell;
ASSERT_HRESULT_SUCCEEDED(shell.CoCreateInstance(L"Shell.Application"));
CComVariant empty;
ASSERT_HRESULT_SUCCEEDED(shell->ShellExecute(CComBSTR(url), empty, empty, empty, empty));

2.9 类型检查

来声称断言类型T1和T2是相同的。 如果满足断言,该函数不执行任何操作。 如果类型不同,函数调用将无法编译,编译器错误消息(取决于编译器)将显示T1和T2的实际值。 这主要在模板代码中有用。

注意:当在类模板或函数模板的成员函数中使用时,StaticAssertTypeEq <T1,T2>()仅在函数实例化时有效。 例如,给定:

1

2

3

4

template <typename T> class Foo {

 public:

  void Bar() { ::testing::StaticAssertTypeEq<int, T>(); }

};

the code:

1

void Test1() { Foo<bool> foo; }

将不会生成编译器错误,因为Foo <bool> :: Bar()永远不会实际实例化。 相反,您需要:

1

void Test2() { Foo<bool> foo; foo.Bar(); }

类型检查失败时,直接导致代码编不过,难得用处就在这?看下面的例子:

template <typename T> class FooType {
public:
    void Bar() { testing::StaticAssertTypeEq<int, T>(); }
};

TEST(TypeAssertionTest, Demo)
{
    FooType<bool> fooType;
    fooType.Bar();
}

2.10 使用返回AssertionResult的函数

虽然EXPECT_PRED *()和friends对快速工作很方便,但是语法不令人满意:你必须使用不同的宏不同的arities,它感觉更像Lisp而不是C ++。 :: testing :: AssertionResult类解决了这个问题。

AssertionResult对象表示断言的结果(无论它是成功还是失败,以及相关联的消息)。 您可以使用以下工厂函数之一创建AssertionResult:

1

2

3

4

5

6

7

8

9

10

11

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对象。

要在布尔断言(例如EXPECT_TRUE())中提供更多可读消息,请编写一个返回AssertionResult而不是bool的谓词函数。 例如,如果您将IsEven()定义为:

1

2

3

4

5

6

::testing::AssertionResult IsEven(int n) {

  if ((n % 2) == 0)

    return ::testing::AssertionSuccess();

  else

    return ::testing::AssertionFailure() << n << " is odd";

}

而不是:

1

2

3

bool IsEven(int n) {

  return (n % 2) == 0;

}

  the failed assertion EXPECT_TRUE(IsEven(Fib(4))) will print:

1

2

3

4

5

Value of: IsEven(Fib(4))

Actual: false (*3 is odd*)

Expected: true

  instead of a more opaque:

1

2

3

4

5

Value of: IsEven(Fib(4))

Actual: false

Expected: true

  如果您希望在EXPECT FALSE和ASSERT_FALSE中看到提供信息的消息,并且在成功的情况下使谓词变慢,您可以提供一个成功消息:

1

2

3

4

5

6

::testing::AssertionResult IsEven(int n) {

  if ((n % 2) == 0)

    return ::testing::AssertionSuccess() << n << " is even";

  else

    return ::testing::AssertionFailure() << n << " is odd";

}

  Then the statement EXPECT_FALSE(IsEven(Fib(6))) will print

1

2

3

4

5

Value of: IsEven(Fib(6))

Actual: true (8 is even)

Expected: false

总结

本篇将常用的断言都介绍了一遍,内容比较多,有些还是很有用的。要真的到写案例的时候,也行只是一两种是最常用的,现在时知道有这么多种选择,以后才方便查询。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值