断言 ######################################## 前言 **************************************** 这篇文章主要总结gtest中的所有断言相关的宏。 gtest中,断言的宏可以理解为分为两类,一类是ASSERT系列,一类是EXPECT系列。一个直观的解释就是: 1. ASSERT_* 系列的断言,当检查点失败时,退出当前函数(注意:并非退出当前案例)。 2. EXPECT_* 系列的断言,当检查点失败时,继续往下执行。 示例 **************************************** .. code-block:: cpp // int型比较,预期值:3,实际值:Add(1, 2) EXPECT_EQ(3, Add(1, 2)) // 假如你的Add(1, 2) 结果为4的话,会在结果中输出: .. code-block:: none 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) .. code-block:: xml 如果你对自动输出的出错信息不满意的话,你还可以通过操作符<<将一些自定义的信息输出,通常,这对于调试或是对一些检查点的补充说明来说,非常有用! 下面举个例子: 如果不使用<<操作符自定义输出的话: .. code-block:: cpp for (int i = 0; i < x.size(); ++i) { EXPECT_EQ(x[i], y[i]); } 看到的结果将是这样的,你根本不知道出错时 i 等于几: .. code-block:: none g:\myproject\c++\gtestdemo\gtestdemo\gtestdemo.cpp(25): error: Value of: y[i] Actual: 4 Expected: x[i] Which is: 3 如果使用<<操作符将一些重要信息输出的话: .. code-block:: cpp for (int i = 0; i < x.size(); ++i) { EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i; } 从输出结果中就可以定位到在 i = 2 时出现了错误。这样的输出结果看起来更加有用,容易理解: .. code-block:: none 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 布尔值检查 **************************************** .. csv-table:: :header: 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*,估计是不常用吧。下面是几个例子: .. code-block:: cpp 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(); ================ ==================== .. code-block:: cpp 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 ======================================== ========================================= ================================================= 例如: .. code-block:: cpp 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个参数的,如果需要测试更多的参数,直接告诉他们。下面看看这个东西怎么用。 .. code-block:: cpp 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 ... ,... ,... ============================================== =============================================== ========================================= 用法示例: .. code-block:: cpp 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 =================================== ==================================== ============================================================================== 同时,还可以使用: .. code-block:: none 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 ===================================== ====================================== ================================ 例如: .. code-block:: cpp CComPtr shell; ASSERT_HRESULT_SUCCEEDED(shell.CoCreateInstance(L"Shell.Application")); CComVariant empty; ASSERT_HRESULT_SUCCEEDED(shell->ShellExecute(CComBSTR(url), empty, empty, empty, empty)); 类型检查 **************************************** 类型检查失败时,直接导致代码编不过,难得用处就在这?看下面的例子: .. code-block:: cpp template class FooType { public: void Bar() { testing::StaticAssertTypeEq(); } }; TEST(TypeAssertionTest, Demo) { FooType fooType; fooType.Bar(); } 总结 **************************************** 本篇将常用的断言都介绍了一遍,内容比较多,有些还是很有用的。要真的到写案例的时候,也行只是一两种是最常用的,现在时知道有这么多种选择,以后才方便查询。