2026/11/6 4:51:23

Gtest

Gtest 一、初始Gtest和框架搭建1.4 DemointFoo(inta,intb){if(a0||b0){throwdont do that;}intca%b;if(c0)returnb;returnFoo(b,c);}#includegtest/gtest.hTEST(FooTest,HandleNoneZeroInput){EXPECT_EQ(2,Foo(4,10));EXPECT_EQ(6,Foo(30,18));}二、断言2.1 前言GTest中断言的宏可以理解为分为两类一类是ASSERT系列一类是EXPECT系列。一个直观的解释就是ASSERT_*系列的断言当检查点失败时退出当前函数注意并非退出当前testcaseEXPECT_*系列的断言当检查点失败时继续往下执行2.2 自定义提示信息实例未使用自定义提示for(inti0;ix.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(inti0;ix.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 assertionVerifiesASSERT_EQ(expected, actual);EXPECT_EQ(expected, actual);expected actualASSERT_NE(val1, val2);EXPECT_NE(val1, val2);val1 ! val2ASSERT_LT(val1, val2);EXPECT_LT(val1, val2);val1 val2ASSERT_LE(val1, val2);EXPECT_LE(val1, val2);val1 val2ASSERT_GT(val1, val2);EXPECT_GT(val1, val2);val1 val2ASSERT_GE(val1, val2);EXPECT_GE(val1, val2);val1 val22.5 字符串检查Fatal assertionNonfatal assertionVerifiesASSERT_STREQ(expected_str,actual_str);EXPECT_STREQ(expected_str,actual_str);same contentASSERT_STRNE(str1, str2);EXPECT_STRNE(str1, str2);the two C strings have different contentASSERT_STRCASEEQ(expected_str, actual_str);EXPECT_STRCASEEQ(expected_str, actual_str);same content, ignoring caseASSERT_STRCASENE(str1,str2);EXPECT_STRCASENE(str1,str2);different content, ignoring case2.6 显示返回成功或失败直接返回成功SUCCEED()返回失败Fatal assertionNonfatal assertionFAIL();ADD_FAILURE();TEST(ExplicitTest,Demo){ADD_FAILURE()Sorry;// None Fatal Asserton继续往下执行。//FAIL() Sorry!; // Fatal Assertion不继续往下执行该案例。SUCCEED();}2.7 异常检查Fatal assertionNonfatal assertionVerifiesASSERT_THROW(statement,exception_type);EXPECT_THROW(statement,exception_type);statement throws an exception of the given typeASSERT_ANY_THROW(statement);EXPECT_ANY_THROW(statement);statement throws an exception of any typeASSERT_NO_THROW(statement);EXPECT_NO_THROW(statement);statement doesn’t throw any exceptionintFoo(inta,intb){if(a0||b0){throwdont do that;}intca%b;if(c0)returnb;returnFoo(b,c);}TEST(FooTest,HandleZeroInput){EXPECT_ANY_THROW(Foo(10,0));EXPECT_THROW(Foo(0,5),char*);}2.8 Predicate Assertions是对ASSERT_TRUE和EXPECT_TRUE的改进使其不仅判断TRUE和FALSE而且能显示其他信息比如输入的参数内容。如下分别是一个输入参数和两个输入参数的使用。Fatal assertionNonfatal assertionVerifiesASSERT_PRED1(pred1, val1);EXPECT_PRED1(pred1, val1);pred1(val1) returns trueASSERT_PRED2(pred2, val1, val2);EXPECT_PRED2(pred2, val1, val2);pred2(val1, val2) returns trueboolMutuallyPrime(intm,intn){returnFoo(m,n)1;}TEST(PredicateAssertionTest,Demo){intm5,n6;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 assertionVerifiesASSERT_FLOAT_EQ(expected, actual);EXPECT_FLOAT_EQ(expected, actual);the two float values are almost equalASSERT_DOUBLE_EQ(expected, actual);EXPECT_DOUBLE_EQ(expected, actual);the two double values are almost equal2.9.1 相近数比较Fatal assertionNonfatal assertionVerifiesASSERT_NEAR(val1, val2, abs_error);EXPECT_NEAR(val1, val2, abs_error);the difference between val1 and val2 doesn’t exceed the given absolute error2.10 Windows HRESULT 检查Fatal assertionNonfatal assertionVerifiesASSERT_HRESULT_SUCCEEDED(expression);EXPECT_HRESULT_SUCCEEDED(expression);expression is a success HRESULTASSERT_HRESULT_FAILED(expression);EXPECT_HRESULT_FAILED(expression);expression is a failure HRESULTCComPtr shell;ASSERT_HRESULT_SUCCEEDED(shell.CoCreateInstance(LShell.Application));CComVariant empty;ASSERT_HRESULT_SUCCEEDED(shell-ShellExecute(CComBSTR(url),empty,empty,empty,empty));2.11 类型检查templatetypenameTclassFooType{public:voidBar(){testing::StaticAssertTypeEqint,T();}};TEST(TypeAssertionTest,Demo){FooTypeboolfooType;fooType.Bar();}三、事件机制3.1 前言事件在案例执行之前或之后做的一些操作。共有三个粒度全局级别的。在所有案例的第一个执行前和所有案例最后一个执行后。TestSuite级别的。在某一批案例中的第一个案例前最后一个案例执行后。TsetCase级别的。每个TestCase前后。特别需要注意区分粒度。粒度解释全局有50个testcaseSetUp在第1个testcase前执行TearDown在第50个testcase后执行。TestSuite有50个testcase其中针对这一个TestSuite的testcase是第20-30个则此SetUpTestCase在第20个testcase前执行TearDownTestCase在第30个testcase后执行。TestCaseSetUp使用此事件的每一个testcase前执行一次TearDown在 使用此事件的每一个testcase后执行一次3.2 全局级别要实现全局级别的事件写一个类继承testing::Environment类实现SetUp和TearDown在main函数中通过testing::AddGlobalTestEnvironment把事件挂进来。我们有50个testcaseSetUp在第1个testcase前执行TearDown在第50个testcase后执行。3.2.1 实现SetUP和TearDownclassFooEnvironment:publictesting::Environment{public:virtualvoidSetUp(){std::coutFoo FooEnvironment SetUPstd::endl;}virtualvoidTearDown(){std::coutFoo FooEnvironment TearDownstd::endl;}public:intdwRet;};3.2.2 挂载事件int_tmain(intargc,_TCHAR*argv[]){testing::AddGlobalTestEnvironment(newFooEnvironment);testing::InitGoogleTest(argc,argv);returnRUN_ALL_TESTS();}3.3 TestSuite事件要实现TestSuite级别(某一批)的事件写一个类继承testing::Test类实现静态方法SetUpTestCase和TearDownTestCase我们有50个testcase其中针对这一个TestSuite的testcase是第20-30个则此SetUpTestCase在第20个testcase前执行TearDownTestCase在第30个testcase后执行。classFooTest:publictesting::Test{protected:staticvoidSetUpTestCase(){shared_resource_new;}staticvoidTearDownTestCase(){deleteshared_resource_;shared_resource_NULL;}staticT*shared_resource_;};在编写测试案例时我们需要使用TEST_F这个宏第一个参数必须是我们上面类的名字代表一个TestSuiteTEST_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执行后执行。classTEST_Command_Parse:publictesting::Test{public:CoreInfo*coreInfo;2.在main函数中通过testing::AddGlobalTestEnvironment把事件挂进来。public:virtualvoidSetUp(){coreInfoInitCoreNetwork();}virtualvoidTearDown(){CloseCoreNetwork(coreInfo);}};#includegtest/gtest.hGTEST_API_intmain(intargc,char**argv){testing::InitGoogleTest(argc,argv);returnRUN_ALL_TESTS();}四、死亡测试//暂缺五、运行参数5.1 命令行参数gtest同样能够处理命令行参数因为在main函数中我们把命令行参数交给了gtest。int_tmain(intargc,_TCHAR*argv[]){testing::InitGoogleTest(argc,argv);returnRUN_ALL_TESTS();}由gtest来搞定命令行问题这样就可以使用命令行参数来使得gtest达到我们想要的效果比如参数作用–gtest_list_tests使用这个参数时将不会执行里面的测试案例而是输出一个案例的列表。5.2 代码中指定FLAGgtest提供了不止一种设置运行参数的方法命令行参数代码中指定FLAG系统环境变量优先级为命令行参数 代码中指定FLAG 系统环境变量代码指定FLAGtesting::GTEST_FLAG(output) xml:代码中指定FLAG可以使用testing::GTEST_FLAG这个宏来设置推荐将这句放在InitGoogleTest之前这样就可以使得对于同样的参数命令行参数优先级高于代码指定。int_tmain(intargc,_TCHAR*argv[]){testing::GTEST_FLAG(output)xml:;testing::InitGoogleTest(argc,argv);returnRUN_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_outputxml[:DIRECTORY_PATH|:FILE_PATH]异常处理异常处理–gtest_break_on_failure调试模式下当案例失败时停止方便调试–gtest_throw_on_failure–gtest_catch_exceptions5.4 总结本篇主要介绍了gtest案例执行时提供的一些参数的使用方法这些参数都非常有用。在实际编写gtest测试案例时肯定会需要用到的时候。至少我现在比较常用的就是–gtest_filter//运行所有测试./my_test--gtest_filter*//只运行 MathOperations 套件下的所有测试./my_test--gtest_filterMathOperations.*–gtest_outputxml[:DIRECTORY_PATH|:FILE_PATH]–gtest_catch_exceptions最后再总结一下我使用过程中遇到的几个问题:同时使用–gtest_filter和–gtest_outputxml:时在xml测试报告中能否只包含过滤后的测试案例的信息。有时我在代码中设置 testing::GTEST_FLAG(catch_exceptions) 1和我在命令行中使用–gtest_catch_exceptions结果稍有不同在代码中设置FLAG方式有时候捕捉不了某些异常但是通过命令行参数的方式一般都不会有问题。这是我曾经遇到过的一个问题最后我的处理办法是既在代码中设置FLAG又在命令行参数中传入–gtest_catch_exceptions。不知道是gtest在catch_exceptions方面不够稳定还是我自己测试案例的问题。