google test 学习笔记2-google test Advanced guide

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共分为:
1. More Assertions
2. Teaching Google Test How to Print Your Values
3. Death Tests
4. Using Assertions in Sub-routines
5. Logging Additional Information
6. Sharing Resources Between Tests in the Same Test Case
7. Global Set-Up and Tear-Down
8. Value Parameterized Tests
9. Typed Tests
10. Type-Parameterized Tests
11. Testing Private Code
12. Catching Failures
13. Getting the Current Test’s Name
14. Extending Google Test by Handling Test Events
15. Running Test Programs: Advanced Options

有的部分部分比较长,有的部分比较短。
这是Advanced Guide的第一部分:更多的断言

content

More Assertions

更多的断言

This section covers some less frequently used, but still significant,
assertions.
这一部分包含了一些不常用的,但是依然很重要的ASSERTIONS

Explicit Success and Failure

明确的成功or失败

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.
下面这三个宏,并不是用来 检测一个值或是表达式,它们只是产生一个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)可能会在未来为它增加一些功能

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。 在一些控制流程中,它们会比一些布尔表达式更有用,比如有一些分支是不能走的,见下例:

switch(expression) {
  case 1: ... some checks ...
  case 2: ... some other checks
  ...
  default: FAIL() << "We shouldn't get here.";
}

Availability: Linux, Windows, Mac.

Exception Assertions

异常断言

These are for verifying that a piece of code throws (or does not throw) an exception of the given type:
这些宏用来验证一些代码是否的,抛出了指定的异常

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

Examples:

ASSERT_THROW(Foo(5), bar_exception);


EXPECT_NO_THROW({
  int n = 5;
  Bar(&n);
});

Availability: Linux, Windows, Mac; since version 1.1.0.

Predicate Assertions for Better Error Messages

预测断言(为了更好的错误信息)

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 提供了三种不同的选择来解决

Using an Existing Boolean Function

使用一个已经存在的布尔型的函数

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 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

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.
prednn,可以是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:

  1. If you see a compiler error “no matching function to call” when using ASSERT_PRED* or EXPECT_PRED*, please see this for how to resolve it.
  2. Currently we only provide predicate assertions of arity <= 5. If you need a higher-arity assertion, let us know.

确实最大只到5
Availability: Linux, Windows, Mac

Using a Function That Returns an AssertionResult

使用返回值为 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.

Using a Predicate-Formatter

使用格式化宏

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 assertionNonfatal assertionVerifies
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, T1val1, T2val2, ... Tnvaln);

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 macro
EXPECT_PRED_FORMATn(XXXXXXXXXXX, val_1,val_2,..., val_n);

需要注意的是,代码中XXXXXXXXXXX部分要完全相同,即要有相同的函数名

Availability: Linux, Windows, Mac.

Floating-Point Comparison

浮点数的比较

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比较,情况会好一点。

Floating-Point Macros

浮点数比较的宏

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

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 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

Availability: Linux, Windows, Mac.

Floating-Point Predicate-Format Functions

浮点数的预测格式比较

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.

Windows HRESULT assertions

These assertions test for HRESULT success or failure.

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

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.

Type Assertions

类型断言

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>()这货用来比较T1T2两个类型是否相同,比如是否同为int。如果相同,这个函数什么也不做,如果不相同,这个函数会产生一个编译错误,错误消息会显示T1T2的真实类型(具体消息的格式及如何显示取决于编译器)。在使用模板的代码中,这个函数会比较有用。

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.

Assertion Placement

断言位置

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,可以考虑将其返回值封闭成输出参数 rightarrow 使用引用或指针

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要非常小心。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值