Gtest

一、初始Gtest和框架搭建

1.4 Demo

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);
}
#include <gtest/gtest.h>

TEST(FooTest, HandleNoneZeroInput)
{
    EXPECT_EQ(2, Foo(4, 10));
    EXPECT_EQ(6, Foo(30, 18));
}

二、断言

2.1 前言

GTest中,断言的宏可以理解为分为两类,一类是ASSERT系列,一类是EXPECT系列。一个直观的解释就是:

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

2.2 自定义提示信息实例

未使用自定义提示

for (int i = 0; i < x.size(); ++i) 
{
    EXPECT_EQ(x[i], y[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;
}

/*
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.3 bool值类型检查

ASSERTEXPECT
检查失败退出函数检查失败继续往下执行
ASSERT_TRUE(condition);EXPECT_TRUE(condition);
ASSERT_FALSE(condition);EXPECT_FALSE(condition);

2.4 数值型检查

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

2.5 字符串检查

Fatal assertionNonfatal assertionVerifies
ASSERT_STREQ(expected_str,actual_str);EXPECT_STREQ(expected_str,actual_str);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);same content, ignoring case
ASSERT_STRCASENE(str1,str2);EXPECT_STRCASENE(str1,str2);different content, ignoring case

2.6 显示返回成功或失败

  1. 直接返回成功 SUCCEED()
  2. 返回失败
Fatal assertionNonfatal assertion
FAIL();ADD_FAILURE();
TEST(ExplicitTest, Demo)
{
    ADD_FAILURE() << "Sorry"; // None Fatal Asserton,继续往下执行。 
	//FAIL() << "Sorry!";     // Fatal Assertion,不继续往下执行该案例。
    SUCCEED();
}

2.7 异常检查

Fatal assertionNonfatal assertionVerifies
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*);
}

2.8 Predicate Assertions

  是对ASSERT_TRUEEXPECT_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
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
*/

2.9 浮点型检查

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

2.9.1 相近数比较

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

2.10 Windows HRESULT 检查

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
CComPtr shell;
ASSERT_HRESULT_SUCCEEDED(shell.CoCreateInstance(L"Shell.Application"));
CComVariant empty;
ASSERT_HRESULT_SUCCEEDED(shell->ShellExecute(CComBSTR(url), empty, empty, empty, empty));

2.11 类型检查

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

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

三、事件机制

3.1 前言

事件:在案例执行之前或之后做的一些操作。
共有三个粒度:

  1. 全局级别的。在所有案例的第一个执行前,和所有案例最后一个执行后。
  2. TestSuite级别的。在某一批案例中的第一个案例前,最后一个案例执行后。
  3. TsetCase级别的。每个TestCase前后。
    特别需要注意区分粒度。
粒度解释
全局有50个testcase,SetUp在第1个testcase前执行,TearDown在第50个testcase后执行。
TestSuite有50个testcase,其中针对这一个TestSuitetestcase是第20-30个,则此SetUpTestCase在第20个testcase前执行,TearDownTestCase在第30个testcase后执行。
TestCaseSetUp使用此事件的每一个testcase前执行一次,TearDown在 使用此事件的每一个testcase后执行一次

3.2 全局级别

  要实现全局级别的事件:

  1. 写一个类,继承testing::Environment类,实现SetUpTearDown
  2. 在main函数中通过testing::AddGlobalTestEnvironment把事件挂进来。

  我们有50个testcase,SetUp在第1个testcase前执行,TearDown在第50个testcase后执行。

3.2.1 实现SetUP和TearDown
class FooEnvironment : public testing::Environment
{
public:    
	virtual void SetUp()
    {
        std::cout << "Foo FooEnvironment SetUP" << std::endl;
    }    
    virtual void TearDown()
    {
        std::cout << "Foo FooEnvironment TearDown" << std::endl;
    }
public:
	int dwRet;
};
3.2.2 挂载事件
int _tmain(int argc, _TCHAR* argv[])
{
    testing::AddGlobalTestEnvironment(new FooEnvironment);
    testing::InitGoogleTest(&argc, argv);    
    return RUN_ALL_TESTS();
}

3.3 TestSuite事件

  要实现TestSuite级别(某一批)的事件:

  1. 写一个类,继承testing::Test类,实现静态方法SetUpTestCaseTearDownTestCase

  我们有50个testcase,其中针对这一个TestSuitetestcase是第20-30个,则此SetUpTestCase在第20个testcase前执行,TearDownTestCase在第30个testcase后执行。

class FooTest : public testing::Test 
{
protected:  
	static void SetUpTestCase() 
	{
	    shared_resource_ = new ;
  	}  
  	static void TearDownTestCase() 
  	{
    	delete shared_resource_;
    	shared_resource_ = NULL;
  	}
  	static T* shared_resource_;
};

在编写测试案例时,我们需要使用TEST_F这个宏,第一个参数必须是我们上面类的名字,代表一个TestSuite

TEST_F(FooTest, Given_When_Then)
{    
	// you can refer to shared_resource here 
}
TEST_F(FooTest, Given_When_Then)
{    
	// you can refer to shared_resource here 
}
3.4 TestCase事件

TestCase是在每个testcase执行前执行,也在每个testcase执行后执行。

class TEST_Command_Parse : public testing::Test
{
public:
    CoreInfo *coreInfo; 2. 在main函数中通过t`esting::AddGlobalTestEnvironment`把事件挂进来。

public:
    virtual void SetUp()
    {
        coreInfo = InitCoreNetwork();
    }
    virtual void TearDown()
    {
        CloseCoreNetwork(coreInfo);
    }
};

#include "gtest/gtest.h"

GTEST_API_ int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

四、死亡测试

//暂缺

五、运行参数

5.1 命令行参数

  gtest同样能够处理命令行参数,因为在main函数中我们把命令行参数交给了gtest。

int _tmain(int argc, _TCHAR* argv[])
{
    testing::InitGoogleTest(&argc, argv);    
    return RUN_ALL_TESTS();
}

  由gtest来搞定命令行问题,这样就可以使用命令行参数来使得gtest达到我们想要的效果,比如:

参数作用
–gtest_list_tests使用这个参数时,将不会执行里面的测试案例,而是输出一个案例的列表。

5.2 代码中指定FLAG

gtest提供了不止一种设置运行参数的方法:

  • 命令行参数
  • 代码中指定FLAG
  • 系统环境变量

  • 优先级为:命令行参数 > 代码中指定FLAG > 系统环境变量
  • 代码指定FLAG:testing::GTEST_FLAG(output) = "xml:"

代码中指定FLAG,可以使用testing::GTEST_FLAG这个宏来设置,推荐将这句放在InitGoogleTest之前,这样就可以使得对于同样的参数,命令行参数优先级高于代码指定。

int _tmain(int argc, _TCHAR* argv[])
{
    testing::GTEST_FLAG(output) = "xml:";
    testing::InitGoogleTest(&argc, argv);    return RUN_ALL_TESTS();
}

5.3 列表

命令行参数说明
–gtest_list_tests
–gtest_filter
–gtest_also_run_disabled_tests
–gtest_repeat=[COUNT]
–gtest_color=(yes\no\auto)
–gtest_print_time
–gtest_output=xml[:DIRECTORY_PATH|:FILE_PATH]
异常处理异常处理
–gtest_break_on_failure调试模式下,当案例失败时停止,方便调试
–gtest_throw_on_failure
–gtest_catch_exceptions

5.4 总结

本篇主要介绍了gtest案例执行时提供的一些参数的使用方法,这些参数都非常有用。在实际编写gtest测试案例时肯定会需要用到的时候。至少我现在比较常用的就是:

  1. –gtest_filter
  2. –gtest_output=xml[:DIRECTORY_PATH|:FILE_PATH]
  3. –gtest_catch_exceptions
    最后再总结一下我使用过程中遇到的几个问题:
  4. 同时使用–gtest_filter和–gtest_output=xml:时,在xml测试报告中能否只包含过滤后的测试案例的信息。
  5. 有时,我在代码中设置 testing::GTEST_FLAG(catch_exceptions) = 1和我在命令行中使用–gtest_catch_exceptions结果稍有不同,在代码中设置FLAG方式有时候捕捉不了某些异常,但是通过命令行参数的方式一般都不会有问题。这是我曾经遇到过的一个问题,最后我的处理办法是既在代码中设置FLAG,又在命令行参数中传入–gtest_catch_exceptions。不知道是gtest在catch_exceptions方面不够稳定,还是我自己测试案例的问题。

6. 深入解析gtest

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值