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

简介:

一、前言

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

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

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

二、示例

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

 

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

g:\myproject\c ++ \gtestdemo\gtestdemo\gtestdemo.cpp( 16 ): error: Value of: Add( 1 2 )
  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 
is 3

 

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

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

 

三、布尔值检查

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(
10 0 ));
    EXPECT_THROW(Foo(
0 5 ),  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, 
3 6 2 );
}
复制代码

失败时,输出信息:

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)之八 - 打造自己的单元测试框架

 

 

本文转自CoderZh博客园博客,原文链接:http://www.cnblogs.com/coderzh/archive/2009/04/06/1430364.html,如需转载请自行联系原作者

相关文章
|
10天前
|
敏捷开发 Java 测试技术
探索软件测试中的自动化测试框架
在软件开发的生命周期中,软件测试扮演着至关重要的角色。随着技术的不断进步和软件项目的日益复杂化,传统的手动测试方法已经无法满足高效、准确的测试需求。自动化测试作为一种提高测试效率和质量的有效手段,越来越受到开发者和测试者的青睐。本文将深入探讨自动化测试框架的重要性、常见的自动化测试工具以及如何选择合适的自动化测试框架。
35 10
|
12天前
|
设计模式 前端开发 JavaScript
自动化测试框架设计原则与最佳实践####
本文深入探讨了构建高效、可维护的自动化测试框架的核心原则与策略,旨在为软件测试工程师提供一套系统性的方法指南。通过分析常见误区,结合行业案例,阐述了如何根据项目特性定制自动化策略,优化测试流程,提升测试覆盖率与执行效率。 ####
38 6
|
12天前
|
人工智能 前端开发 测试技术
探索软件测试中的自动化框架选择与优化策略####
本文深入剖析了当前主流的自动化测试框架,通过对比分析各自的优势、局限性及适用场景,为读者提供了一套系统性的选择与优化指南。文章首先概述了自动化测试的重要性及其在软件开发生命周期中的位置,接着逐一探讨了Selenium、Appium、Cypress等热门框架的特点,并通过实际案例展示了如何根据项目需求灵活选用与配置框架,以提升测试效率和质量。最后,文章还分享了若干最佳实践和未来趋势预测,旨在帮助测试工程师更好地应对复杂多变的测试环境。 ####
38 4
|
12天前
|
监控 jenkins 测试技术
自动化测试框架的构建与实践
【10月更文挑战第40天】在软件开发周期中,测试环节扮演着至关重要的角色。本文将引导你了解如何构建一个高效的自动化测试框架,并深入探讨其设计原则、实现方法及维护策略。通过实际代码示例和清晰的步骤说明,我们将一起探索如何确保软件质量,同时提升开发效率。
29 1
|
18天前
|
机器学习/深度学习 前端开发 测试技术
探索软件测试中的自动化测试框架选择与优化策略####
本文深入探讨了在当前软件开发生命周期中,自动化测试框架的选择对于提升测试效率、保障产品质量的重要性。通过分析市场上主流的自动化测试工具,如Selenium、Appium、Jest等,结合具体项目需求,提出了一套系统化的选型与优化策略。文章首先概述了自动化测试的基本原理及其在现代软件开发中的角色变迁,随后详细对比了各主流框架的功能特点、适用场景及优缺点,最后基于实际案例,阐述了如何根据项目特性量身定制自动化测试解决方案,并给出了持续集成/持续部署(CI/CD)环境下的最佳实践建议。 --- ####
|
7天前
|
JavaScript 安全 编译器
TypeScript 与 Jest 测试框架的结合使用,从 TypeScript 的测试需求出发,介绍了 Jest 的特点及其与 TypeScript 结合的优势,详细讲解了基本测试步骤、常见测试场景及异步操作测试方法
本文深入探讨了 TypeScript 与 Jest 测试框架的结合使用,从 TypeScript 的测试需求出发,介绍了 Jest 的特点及其与 TypeScript 结合的优势,详细讲解了基本测试步骤、常见测试场景及异步操作测试方法,并通过实际案例展示了其在项目中的应用效果,旨在提升代码质量和开发效率。
25 6
|
3天前
|
机器学习/深度学习 人工智能 Java
探索软件测试中的自动化框架选择与优化策略####
本文深入探讨了在软件测试领域,面对众多自动化测试框架时,如何根据项目特性、团队技能及长远规划做出最佳选择,并进一步阐述了优化这些框架以提升测试效率与质量的策略。通过对比分析主流自动化测试框架的优劣,结合具体案例,本文旨在为测试团队提供一套实用的框架选型与优化指南。 ####
|
3天前
|
敏捷开发 前端开发 Java
软件测试中的自动化测试框架选择与实践
在当今软件开发生命周期中,自动化测试已成为提升软件质量和开发效率的关键手段。本文旨在探讨自动化测试框架的选择标准及其在实际项目中的应用实践。通过对主流自动化测试框架的分析比较,结合具体案例,本文将阐述如何根据项目需求和团队特点选择合适的自动化测试工具,并分享实施过程中的经验教训。
10 1
|
18天前
|
测试技术 API Android开发
探索软件测试中的自动化框架选择与实践####
本文深入探讨了软件测试领域内,面对众多自动化测试框架时,如何依据项目特性和团队需求做出明智选择,并分享了实践中的有效策略与技巧。不同于传统摘要的概述方式,本文将直接以一段实践指南的形式,简述在选择自动化测试框架时应考虑的核心要素及推荐路径,旨在为读者提供即时可用的参考。 ####
|
13天前
|
开发框架 安全 .NET
.NET使用Moq开源模拟库简化单元测试
.NET使用Moq开源模拟库简化单元测试~
下一篇
无影云桌面