Now that you have read Primer and learned how to write tests using Google Test, it’s time to learn some new tricks. This document will show you more assertions as well as how to construct complex failure messages, propagate fatal failures, reuse and speed up your test fixtures, and use various flags with your tests.
這篇教程會展現 更多類型的斷言、如何去構建一個複雜的失敗消息、傳播失敗的消息、重用fixtures並提速測試過程以及如何使用豐富的gtest flags
Advanced Guide共分爲:ios
有的部分部分比較長,有的部分比較短。
這是Advanced Guide的第一部分:更多的斷言shell
content
express
更多的斷言app
This section covers some less frequently used, but still significant,
assertions.
這一部分包含了一些不經常使用的,可是依然很重要的ASSERTIONSless
明確的成功or失敗ide
These three assertions do not actually test a value or expression. Instead,
they generate a success or failure directly. Like the macros that actually
perform a test, you may stream a custom failure message into the them.
<font color="green"下面這三個宏,並非用來 檢測一個值或是表達式,它們只是產生一個SUCCESS
或者FAILURE
的消息而已。你能夠用它來流輸出一個自定義的消息。函數
SUCCEED(); |
---|
Generates a success. This does NOT make the overall test succeed. A test is considered successful only if none of its assertions fail during its execution.
SUCCEED()
宏生成一個success
消息,可是,它並不能代表這一條測試是成功的,只有當一個測試的全部斷言都是成功的,這個測試纔是成功的。測試
Note: SUCCEED()
is purely documentary and currently doesn’t generate any user-visible output. However, we may add SUCCEED()
messages to Google Test’s output in the future.
目前,SUCCEED()
並不能產生一個用戶可見的輸出,咱們(the author)可能會在將來爲它增長一些功能ui
FAIL(); |
ADD_FAILURE(); |
ADD_FAILURE_AT(" file_path", line_number); |
---|
FAIL()
generates a fatal failure, while ADD_FAILURE()
and ADD_FAILURE_AT()
generate a nonfatal failure. These are useful when control flow, rather than a Boolean expression, deteremines the test’s success or failure. For example, you might want to write something like:
FAIL()
產生一個fatal failure,而ADD_FAILURE()
和ADD_FAILURE_AT()
產生一個nonfatal failure。 在一些控制流程中,它們會比一些布爾表達式更有用,好比有一些分支是不能走的,見下例:this
switch(expression) { case 1: ... some checks ... case 2: ... some other checks ... default: FAIL() << "We shouldn't get here.";}
Availability: Linux, Windows, Mac.
異常斷言
These are for verifying that a piece of code throws (or does not throw) an exception of the given type:
這些宏用來驗證一些代碼是否的,拋出了指定的異常
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 |
Examples:
ASSERT_THROW(Foo(5), bar_exception);EXPECT_NO_THROW({ int n = 5; Bar(&n);});
Availability: Linux, Windows, Mac; since version 1.1.0.
預測斷言(爲了更好的錯誤信息)
Even though Google Test has a rich set of assertions, they can never be complete, as it’s impossible (nor a good idea) to anticipate all the scenarios a user might run into. Therefore, sometimes a user has to use EXPECT_TRUE()
to check a complex expression, for lack of a better macro. This has the problem of not showing you the values of the parts of the expression, making it hard to understand what went wrong. As a workaround, some users choose to construct the failure message by themselves, streaming it into EXPECT_TRUE()
. However, this is awkward especially when the expression has side-effects or is expensive to evaluate.
儘管gtest提供了豐富多樣的斷言,但它不可能覆蓋全部的用戶可能須要的使用狀況,有時候,用戶不得不用EXPECT_TURE
去檢查一個比較複雜的表達式,由於沒有合適的宏能夠用,在這種狀況下,一旦出錯的話,並不能把相關的參數信息打印出來,做爲一個workaround,一些用戶就自已構造了一些錯誤信息輸出。這樣處理顯得很尷尬很笨拙,尤爲是這個複雜的表達式有side-effect或這個表達式拆分估值比較麻煩的時候
Google Test gives you three different options to solve this problem:
針對這種問題, gtest 提供了三種不一樣的選擇來解決
使用一個已經存在的布爾型的函數
If you already have a function or a functor that returns bool
(or a type that can be implicitly converted to bool
), you can use it in a predicate assertion to get the function arguments printed for free:
若是你已經有一個返回布爾的函數(沒有能夠臨時寫一個),那麼你可使用下面的函數:
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 |
… | … | … |
In the above, predn is an n-ary predicate function or functor, where val1, val2, …, and valn are its arguments. The assertion succeeds if the predicate returns true
when applied to the given arguments, and fails otherwise. When the assertion fails, it prints the value of each argument. In either case, the arguments are evaluated exactly once.
predn 的 n,能夠是0,1,2,3,4,5(所說目前只支持5個), 表示了後面有幾個值,若是這個宏失敗了的話,就會打印出全部的表達式的結果(val),這引發參數表達式只會被計算一次。
Here’s an example. Given
// Returns true iff m and n have no common divisors except 1.bool MutuallyPrime(int m, int n) { ... }const int a = 3;const int b = 4;const int c = 10;
the assertion EXPECT_PRED2(MutuallyPrime, a, b);
will succeed, while the
assertion EXPECT_PRED2(MutuallyPrime, b, c);
will fail with the message
EXPECT_PRED2(MutuallyPrime, b, c);
失敗後,會打印以下結果,能夠看出,它會自動打印傳入的參數:b,c的值。
!MutuallyPrime(b, c) is false, where
b is 4
c is 10
Notes:
ASSERT_PRED*
or EXPECT_PRED*
, please see this for how to resolve it.確實最大隻到5
Availability: Linux, Windows, Mac
使用返回值爲 AssertionResult
類型的函數
While EXPECT_PRED*()
and friends are handy for a quick job, the syntax is not satisfactory: you have to use different macros for different arities, and it feels more like Lisp than C++. The ::testing::AssertionResult
class solves this problem.
雖然EXPECT_PRED*()
和它的小夥伴們能快速處理多個參數的問題,可是這個語法看起來不是很優美,由於不一樣的參數個數,你得調用不一樣的宏,若是多於5個目前尚未辦法處理,這樣看起來更像是Lisp,而不是C++。 而類 ::testing::AssertionResult
能夠解決這個問題
An AssertionResult
object represents the result of an assertion (whether it’s a success or a failure, and an associated message). You can create an AssertionResult
using one of these factory functions:
一個AssertionResult
對象表明了一個斷言結果(不論是SUCCESS或者是FAILURE,都有一個消息)。你可使用這些工廠方法來建立一個AssertionResult
對象。
namespace testing {// Returns an AssertionResult object to indicate that an assertion has// succeeded.AssertionResult AssertionSuccess();// Returns an AssertionResult object to indicate that an assertion has// failed.AssertionResult AssertionFailure();}
You can then use the <<
operator to stream messages to the AssertionResult
object.
經過AssertionResult
對象,可使用流操做符<<
來輸出一些須要的信息。
To provide more readable messages in Boolean assertions (e.g. EXPECT_TRUE()
), write a predicate function that returns AssertionResult
instead of bool
. For example, if you define IsEven()
as:
在布爾斷言中,爲了提供更好的更豐富的錯誤診斷信息,能夠構造一個預測函數,返回AssertionResult
代替返回bool
:見下例
::testing::AssertionResult IsEven(int n) { if ((n % 2) == 0) return ::testing::AssertionSuccess(); else return ::testing::AssertionFailure() << n << " is odd";}
instead of:
bool IsEven(int n) { return (n % 2) == 0;}
the failed assertion EXPECT_TRUE(IsEven(Fib(4)))
will print:
Value of: IsEven(Fib(4))
Actual: false (*3 is odd*)
Expected: true
instead of a more opaque
Value of: IsEven(Fib(4))
Actual: false
Expected: true
If you want informative messages in EXPECT_FALSE
and ASSERT_FALSE
as well, and are fine with making the predicate slower in the success
case, you can supply a success message:
若是你想要更豐富的信息,一樣的,你也能夠在SUCCESS 的狀況下輸出一些本身想要的信息,見下例:
::testing::AssertionResult IsEven(int n) { if ((n % 2) == 0) return ::testing::AssertionSuccess() << n << " is even"; else return ::testing::AssertionFailure() << n << " is odd";}
Then the statement EXPECT_FALSE(IsEven(Fib(6)))
will print
Value of: IsEven(Fib(6))
Actual: true (8 is even)
Expected: false
Availability: Linux, Windows, Mac; since version 1.4.1.
使用格式化宏
If you find the default message generated by (ASSERT|EXPECT)_PRED*
and (ASSERT|EXPECT)_(TRUE|FALSE)
unsatisfactory, or some arguments to your predicate do not support streaming to ostream
, you can instead use the following predicate-formatter assertions to fully customize how the message is formatted:
下面的這些宏,能夠徹底的自定義輸出消息的格式
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 |
... |
... |
... |
The difference between this and the previous two groups of macros is that instead of a predicate, (ASSERT|EXPECT)_PRED_FORMAT*
take a predicate-formatter (pred_formatn), which is a function or functor with the signature:
這些宏和上面介紹的宏(ASSERT_PRED*
)最大的不一樣是多了_FORMAT*
部分,這些宏通常與下面的函數一塊兒使用:
::testing::AssertionResult PredicateFormattern(const char*
expr1, const char*
expr2, ... const char*
exprn, T1
val1, T2
val2, ... Tn
valn);
where val1, val2, …, and valn are the values of the predicate arguments, and expr1, expr2, …, and exprn are the corresponding expressions as they appear in the source code. The types T1
, T2
, …, and Tn
can be either value types or reference types. For example, if an argument has type Foo
, you can declare it as either Foo
or const Foo&
, whichever is appropriate.
val1, val2, …, _valn_是運行被測試函數須要的參數,這些參數的類型能夠是值類型,也能夠是引用類型。 expr1, expr2,…, exprn 是對應於 val* 的字符串。
若是 val1 是引用類型,那麼 expr1 應該是什麼呢?它一直是字符串,能表示這個對象的哪一部分呢?仍是對象的名字?
A predicate-formatter returns a ::testing::AssertionResult
object to indicate whether the assertion has succeeded or not. The only way to create such an object is to call one of these factory functions:
一個 predicate-formatter返回一個::testing::AssertionResult
的對象,用來標識SUCCESS或者FAILURE。建立 predicate-formatter的惟一辦法是使用這個工廠函數。
As an example, let’s improve the failure message in the previous example, which uses EXPECT_PRED2()
:
// Returns the smallest prime common divisor of m and n,// or 1 when m and n are mutually prime.int SmallestPrimeCommonDivisor(int m, int n) { ... }// A predicate-formatter for asserting that two integers are mutually prime.::testing::AssertionResult AssertMutuallyPrime(const char* m_expr, const char* n_expr, int m, int n) { if (MutuallyPrime(m, n)) return ::testing::AssertionSuccess(); return ::testing::AssertionFailure() << m_expr << " and " << n_expr << " (" << m << " and " << n << ") are not mutually prime, " << "as they have a common divisor " << SmallestPrimeCommonDivisor(m, n);}
With this predicate-formatter, we can use
EXPECT_PRED_FORMAT2(AssertMutuallyPrime, b, c);
to generate the message
b and c (4 and 10) are not mutually prime, as they have a common divisor 2.
As you may have realized, many of the assertions we introduced earlier are special cases of (EXPECT|ASSERT)_PRED_FORMAT*
. In fact, most of them are indeed defined using (EXPECT|ASSERT)_PRED_FORMAT*
.
其實前面介紹的一些簡單的斷言都是(EXPECT|ASSERT)_PRED_FORMAT*
的特例,它們大多數的內部實現都是用的(EXPECT|ASSERT)_PRED_FORMAT*
在使用(EXPECT|ASSERT)_PRED_FORMAT*
時,須要一個predicate-formatter
函數來配合使用,配合方式以下:
//predicate-formatter::testing::AssertionResult XXXXXXXXXXX(const char* expr_1, const char* expr_2, ... , const char* expr_n, T1 val_1, T2 val_2, ... , Tn val_n){ //code here}//the macroEXPECT_PRED_FORMATn(XXXXXXXXXXX, val_1,val_2,..., val_n);
須要注意的是,代碼中XXXXXXXXXXX部分要徹底相同,即要有相同的函數名
Availability: Linux, Windows, Mac.
浮點數的比較
Comparing floating-point numbers is tricky. Due to round-off errors, it is very unlikely that two floating-points will match exactly. Therefore, ASSERT_EQ
‘s naive comparison usually doesn’t work. And since floating-points can have a wide value range, no single fixed error bound works. It’s better to compare by a fixed relative error bound, except for values close to 0 due to the loss of precision there.
浮點數存在截斷偏差,兩個浮點數之間通常不能精確的相等,因此之間的比較宏都不能用於浮點數的比較,並且浮點數表示的範圍很大,遠比一樣佔據4個字節的int表示的範圍大,那麼它的分辨率必定是很低。因此最好使用相對偏差來進行比較,除了跟0相比。
In general, for floating-point comparison to make sense, the user needs to carefully choose the error bound. If they don’t want or care to, comparing in terms of Units in the Last Place (ULPs) is a good default, and Google Test provides assertions to do this. Full details about ULPs are quite long; if you want to learn more, see this article on float comparison.
通常來講,對於浮點數的比較,用戶須要自已指定偏差範圍,若是不想指定或是對這個不關心的話, 使用ULPs是一個很是好的選擇,gtest也提供了相應的斷言。
須要注意的是,因爲浮點表示的範圍很是大,以經常使用的float和int爲例,他們都佔據4個字節,可是float的範圍很大,float是使用的二進制的科學計數法,對應到十進制來講,只有6到7位的有效數字,若是一個float比較大時,用非科學計數法表示時,其小數位乃至個位、十位,都有多是不精確的,因此在比較時,能夠考慮兩數相減再與0.0f比較,狀況會好一點。
浮點數比較的宏
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 |
By 「almost equal」, we mean the two values are within 4 ULP’s from each other.
對於浮點數比較下的默認相等,這兩個宏指的是小於 有個 ULP’s
The following assertions allow you to choose the acceptable error bound:
下面的宏容許用戶本身指定一個精度來進行比較
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 |
Availability: Linux, Windows, Mac.
浮點數的預測格式比較
Some floating-point operations are useful, but not that often used. In order to avoid an explosion of new macros, we provide them as predicate-format functions that can be used in predicate assertion macros (e.g. EXPECT_PRED_FORMAT2
, etc).
雖然一些浮點數的操做頗有用,可是卻不怎麼經常使用,爲了不定義大量的浮點數相關的宏,這裏定義了 _predicate-format_宏來
EXPECT_PRED_FORMAT2(::testing::FloatLE, val1, val2);EXPECT_PRED_FORMAT2(::testing::DoubleLE, val1, val2);
Verifies that val1 is less than, or almost equal to, val2. You can replace EXPECT_PRED_FORMAT2
in the above table with ASSERT_PRED_FORMAT2
.
Availability: Linux, Windows, Mac.
These assertions test for HRESULT
success or failure.
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 |
The generated output contains the human-readable error message associated with the HRESULT
code returned by expression.
這些宏會輸出一些人類可讀的錯誤消息
You might use them like this:
CComPtr shell;ASSERT_HRESULT_SUCCEEDED(shell.CoCreateInstance(L"Shell.Application"));CComVariant empty;ASSERT_HRESULT_SUCCEEDED(shell->ShellExecute(CComBSTR(url), empty, empty, empty, empty));
Availability: Windows.
類型斷言
You can call the function
::testing::StaticAssertTypeEq<T1, T2>();
to assert that types T1
and T2
are the same. The function does nothing if the assertion is satisfied. If the types are different, the function call will fail to compile, and the compiler error message will likely (depending on the compiler) show you the actual values of T1
and T2
. This is mainly useful inside template code.
::testing::StaticAssertTypeEq<T1, T2>()
這貨用來比較T1
和T2
兩個類型是否相同,好比是否同爲int
。若是相同,這個函數什麼也不作,若是不相同,這個函數會產生一個編譯錯誤,錯誤消息會顯示T1
和T2
的真實類型(具體消息的格式及如何顯示取決於編譯器)。在使用模板的代碼中,這個函數會比較有用。
Caveat: When used inside a member function of a class template or a function template, StaticAssertTypeEq<T1, T2>()
is effective only if the function is instantiated. For example, given:
template <typename T> class Foo {public: void Bar() { ::testing::StaticAssertTypeEq<int, T>(); }};
the code:
void Test1() { Foo<bool> foo; }
will not generate a compiler error, as Foo<bool>::Bar()
is never
actually instantiated. Instead, you need:
void Test2() { Foo<bool> foo; foo.Bar(); }
to cause a compiler error.
注意: 想要用這個函數來檢測模板函數中類型是否匹配或相同,必須保證使用這個函數的代碼會被執行到,不然這個函數是不會起做用的。詳見上例。
Availability: Linux, Windows, Mac; since version 1.3.0.
斷言位置
You can use assertions in any C++ function. In particular, it doesn’t have to be a method of the test fixture class. The one constraint is that assertions that generate a fatal failure (FAIL*
and ASSERT_*
) can only be used in void-returning functions. This is a consequence of Google Test not using exceptions. By placing it in a non-void function you’ll get a confusing compile error like "error: void value not ignored as it ought to be"
.
能夠在代碼的任何位置處使用斷言,除了產生fatal error 的ASSERT_*
等,他們只能在返回值爲void
的函數內使用。這是由於gtest沒有使用異常,若是把它們放在了返回值不爲void
的函數體內,可能會產生一個編譯錯相似於:"error: void value not ignored as it ought to be"
If you need to use assertions in a function that returns non-void, one option is to make the function return the value in an out parameter instead. For example, you can rewrite T2 Foo(T1 x)
to void Foo(T1 x, T2* result)
. You need to make sure that *result
contains some sensible value even when the function returns prematurely. As the function now returns void
, you can use any assertion inside of it.
若是非要返回值不爲void
的函數內使用這些fatal error的ASSERTION,能夠考慮將其返回值封閉成輸出參數
使用引用或指針
If changing the function’s type is not an option, you should just use assertions that generate non-fatal failures, such as ADD_FAILURE*
and EXPECT_*
.
若是不考慮上面將返回值封閉成參數的狀況,那麼就只能用non-fatal ASSERTIONS了
Note: Constructors and destructors are not considered void-returning functions, according to the C++ language specification, and so you may not use fatal assertions in them. You’ll get a compilation error if you try. A simple workaround is to transfer the entire body of the constructor or destructor to a private void-returning method. However, you should be aware that a fatal assertion failure in a constructor does not terminate the current test, as your intuition might suggest; it merely returns from the constructor early, possibly leaving your object in a partially-constructed state. Likewise, a fatal assertion failure in a destructor may leave your object in a partially-destructed state. Use assertions carefully in these situations!
注意,構造函數和析構函數並非返回值爲void
的函數。因此它們也不能用fatal error的assertion,不過能夠考慮將他們的函數體拎出來 ,放到一個返回值爲void
的函數內,這樣就可使用fatal error的assertion了。不過須要注意的是,若是在這些fatal assertion斷言失敗的話,只會提早退出構造/析構函數,並不會終止程序運算,這樣能夠會使你的對象處於一個部分構造/析構的狀態,因此,在構造/析構函數中使用fatal assertion要很是當心。