Google開源C++單元測試框架Google Test系列(gtest)之斷言
gtest中,斷言的巨集可以理解為分為兩類,一類是ASSERT系列,一類是EXPECT系列。一個直觀的解釋就是:
ASSERT_* 系列的斷言,當檢查點失敗時,退出當前函式(注意:並非退出當前案例)。
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裡的話,將輸出:
<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();
}