玩转Google开源C++单元测试框架Google Test系列(gtest)之二 - 断言

一、前言

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

  1. ASSERT_* 系列的断言,当检查点失败时,退出当前函数(注意:并非退出当前案例)。

  2. EXPECT_* 系列的断言,当检查点失败时,继续往下执行。

二、示例

// int型比较,预期值:3,实际值:Add(1, 2) EXPECT_EQ(3, Add(12)) // ![](http://www.cnblogs.com/Images/dot.gif)

 

假如你的Add(1, 2) 结果为4的话,会在结果中输出:

g:\myproject\c++\gtestdemo\gtestdemo\gtestdemo.cpp(16): error: Value of: Add(12)   Actual: 4 Expected:3

如果是将结果输出到xml里的话,将输出:(关于将结果输出为xml,见:http://www.cnblogs.com/coderzh/archive/2009/04/10/1432789.html

<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]); }

看到的结果将是这样的,你根本不知道出错时 i 等于几:

g:\myproject\c++\gtestdemo\gtestdemo\gtestdemo.cpp(25): error: Value of: y[i]   Actual: 4 Expected: x[i] Which is3

 

如果使用<<操作符将一些重要信息输出的话:

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 is3 Vectors x and y differ at index 2

 

三、布尔值检查

**Fatal assertion** **Nonfatal assertion** **Verifies**
ASSERT_TRUE(_condition_); EXPECT_TRUE(_condition_); _condition_ is true
ASSERT_FALSE(_condition_); EXPECT_FALSE(_condition_); _condition_ is false

 

四、数值型数据检查

**Fatal assertion** **Nonfatal assertion** **Verifies**
ASSERT_EQ(_expected_, _actual_); EXPECT_EQ(_expected_, _actual_); _expected_ == _actual_
ASSERT_NE(_val1_, _val2_); EXPECT_NE(_val1_, _val2_); _val1_ != _val2_
ASSERT_LT(_val1_, _val2_); EXPECT_LT(_val1_, _val2_); _val1_ < _val2_
ASSERT_LE(_val1_, _val2_); EXPECT_LE(_val1_, _val2_); _val1_ <= _val2_
ASSERT_GT(_val1_, _val2_); EXPECT_GT(_val1_, _val2_); _val1_ > _val2_
ASSERT_GE(_val1_, _val2_); EXPECT_GE(_val1_, _val2_); _val1_ >= _val2_

 

五、字符串检查

**Fatal assertion** **Nonfatal assertion** **Verifies**
ASSERT_STREQ(_expected_str_, _actual_str_); EXPECT_STREQ(_expected_str_, _actual_str_); the two C strings have the same content
ASSERT_STRNE(_str1_, _str2_); EXPECT_STRNE(_str1_, _str2_); the two C strings have different content
ASSERT_STRCASEEQ(_expected_str_, _actual_str_); EXPECT_STRCASEEQ(_expected_str_, _actual_str_); the two C strings have the same content, ignoring case
ASSERT_STRCASENE(_str1_, _str2_); EXPECT_STRCASENE(_str1_, _str2_); 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());
}

 

六、显示返回成功或失败

直接返回成功:SUCCEED();

返回失败:

**Fatal assertion** **Nonfatal assertion**
FAIL(); ADD_FAILURE();

 

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

    SUCCEED();
}

七、异常检查

**Fatal assertion** **Nonfatal assertion** **Verifies**
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

 

例如:

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(
100));
    EXPECT_THROW(Foo(
05), char*);
}

八、Predicate Assertions

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

**Fatal assertion** **Nonfatal assertion** **Verifies**
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
... ... ...

 

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

如果对这样的输出不满意的话,还可以自定义输出格式,通过如下:

**Fatal assertion** **Nonfatal assertion** **Verifies**
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, 
362);
}

失败时,输出信息:

error: 3 和 6 的最大公约数应该是:3 而不是:2

是不是更温馨呢,呵呵。

九、浮点型检查

**Fatal assertion** **Nonfatal assertion** **Verifies**
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 assertion** **Nonfatal assertion** **Verifies**
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);

 

十、Windows HRESULT assertions

**Fatal assertion** **Nonfatal assertion** **Verifies**
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

 

例如:

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

 

十一、类型检查

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

template <typename T> class FooType {
public:
    
void Bar() { testing::StaticAssertTypeEq<int, T>(); }
};
TEST(TypeAssertionTest, Demo)
{
    FooType
<bool> fooType;
    fooType.Bar();
}

 

十二、总结

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

系列链接:

1.玩转Google开源C++单元测试框架Google Test系列(gtest)之一 - 初识gtest

2.玩转Google开源C++单元测试框架Google Test系列(gtest)之二 - 断言

3.玩转Google开源C++单元测试框架Google Test系列(gtest)之三 - 事件机制

4.玩转Google开源C++单元测试框架Google Test系列(gtest)之四 - 参数化

5.玩转Google开源C++单元测试框架Google Test系列(gtest)之五 - 死亡测试

6.玩转Google开源C++单元测试框架Google Test系列(gtest)之六 - 运行参数

7.玩转Google开源C++单元测试框架Google Test系列(gtest)之七 - 深入解析gtest

8.玩转Google开源C++单元测试框架Google Test系列(gtest)之八 - 打造自己的单元测试框架

 

[温馨提示]:该文章由原博客园导入而来,如排版效果不佳,请移步:http://www.cnblogs.com/coderzh/archive/2009/04/06/1430364.html

微信扫一扫交流

作者:CoderZh
微信关注:hacker-thinking (一个程序员的思考)
本文出处:https://blog.coderzh.com/2009/04/06/1430364/
文章版权归本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。