GoogleTest Advanced 官方doc 机翻

GoogleTest Advanced 官方doc 机翻

Introduction

Now that you have read the GoogleTest Primer and learned how to
write tests using GoogleTest, 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.

现在你已经阅读了 GoogleTest Primer 并学会了如何使用它使用GoogleTest编写测试,是时候学习一些新技巧了。这个文档将向您展示更多断言以及如何构造复杂的失败消息,传播致命故障,重用和加速测试固件,以及在测试中使用各种标志。

More Assertions

This section covers some less frequently used, but still significant,
assertions.

本节将介绍一些不太常用但仍然很重要的内容,断言

Explicit Success and Failure

See Explicit Success and Failure in
the Assertions Reference.

请参阅 Explicit Success and Failure断言引用。

Exception Assertions

See Exception Assertions in the Assertions Reference.

请参阅断言引用中的Exception Assertions

Predicate Assertions for Better Error Messages

谓词断言,以获得更好的错误消息

Even though GoogleTest has a rich set of assertions, they can never be complete,as it’s impossible (nor a good idea) to anticipate all scenarios a user mightrun 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.

尽管GoogleTest有丰富的断言集,但它们永远不可能是完整的,因为它不可能(也不是一个好主意)预测用户可能进入的所有场景。因此,有时用户不得不使用 EXPECT_TRUE() 来检查复杂的表达式,因为缺乏更好的宏。这样做的问题是,你无法看到表达式各部分的值,很难理解哪里出了问题。作为一种变通方法,一些用户选择自己构建失败消息,将其流式传输到 EXPECT_TRUE() 中。然而,这很尴尬,尤其是当表达式有副作用或计算代价很高时。

GoogleTest gives you three different options to solve this problem:

GoogleTest为你提供了三种不同的选项来解决这个问题:

Using an Existing Boolean Function 使用现有的 Boolean 函数

If you already have a function or 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. See EXPECT_PRED* in the Assertions Reference for details.

如果你已经有一个返回bool的函数或functor(或者可以隐式转换为bool的类型),你可以在断言中使用它来免费打印函数参数。请参阅断言参考中的 EXPECT_PRED*以了解详情。

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*()和它的朋友们可以方便地快速完成工作,但语法并不令人满意:你必须对不同的对象使用不同的宏,而且它感觉更像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对象代表了断言的结果(无论是成功还是失败,以及相关的消息)。你可以使用以下工厂函数创建一个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:

在布尔断言中提供更可读的消息(例如:“EXPECT_TRUE()”), 写一个返回AssertionResult而不是bool的谓词函数。为 例如,如果你将IsEven()定义为:

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:

失败的断言 EXPECT_TRUE(IsEven(Fib(4))) 会打印

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(one third of Boolean assertions in the Google code base are negative ones), and are fine with making the predicate slower in the success case, you can supply a success message:

如果你想在EXPECT_FALSEASSERT_FALSE中也得到信息丰富的消息(谷歌代码基中三分之一的布尔断言是否定的),并且可以在成功的情况下让谓词变慢,你可以提供一个成功消息:

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

EXPECT_FALSE(IsEven(Fib(6))) 语句会打印

  Value of: IsEven(Fib(6))
     Actual: true (8 is even)
  Expected: false
Using a Predicate-Formatter / 使用谓词格式化器

If you find the default message generated by EXPECT_PRED* and EXPECT_TRUE unsatisfactory, or some arguments to your predicate do not support streaming to ostream, you can instead use predicate-formatter assertions to fully customize how the message is formatted. See EXPECT_PRED_FORMAT* in the Assertions Reference for details.

如果你发现 EXPECT_PRED*EXPECT_TRUE 生成的默认消息不令人满意,或者你的谓词的一些参数不支持流到 ostream ,你可以使用 predicate-formatter assertions完全 自定义消息的格式化方式。请参阅断言参考中的 EXPECT_PRED_FORMAT* 以了解详情。

Floating-Point Comparison

Floating-Point 比较

See Floating-Point Comparison in the Assertions Reference.

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 the predicate assertion macro EXPECT_PRED_FORMAT2, for example:

有些浮点运算很有用,但不太常用。为了避免新宏的数量爆炸,我们将它们作为谓词格式函数提供,可以在谓词断言宏 EXPECT_PRED_FORMAT2 中使用,例如:

using ::testing::FloatLE;
using ::testing::DoubleLE;
...
EXPECT_PRED_FORMAT2(FloatLE, val1, val2);
EXPECT_PRED_FORMAT2(DoubleLE, val1, val2);

The above code verifies that val1 is less than, or approximately equal to,
val2.

上面的代码验证了val1小于或近似等于: “val2”。

Asserting Using gMock Matchers(使用gMock匹配器进行断言)

See EXPECT_THAT in the Assertions
Reference.

请参阅 Assertions Reference 中的 EXPECT_THAT

More String Assertions (更多关于 String Assertions)

更多关于 String Assertions

(Please read the previous section first if you haven’t.)

(如果还没有阅读 前一节 请先阅读。)

You can use the gMock string matchers with EXPECT_THAT to do more string comparison tricks (sub-string, prefix, suffix, regular expression, and etc). For example,

你可以使用gMock string matchers’ EXPECT_THAT ’ 来进行更多的字符串比较技巧(子字符串、前缀、后缀、正则表达式等)。例如,

using ::testing::HasSubstr;
using ::testing::MatchesRegex;
...
  ASSERT_THAT(foo_string, HasSubstr("needle"));
  EXPECT_THAT(bar_string, MatchesRegex("\\w*\\d+"));

Windows HRESULT assertions (Windows HRESULT 断言)

See Windows HRESULT Assertions in the
Assertions Reference.

请阅读 Assertions Reference 中的 Windows HRESULT Assertions .

Type Assertions (type 断言)

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, the compiler error message will say that T1 and T2 are not the same type and most likely (depending on the compiler) show you the actual values of T1 and T2. This is mainly useful inside template code.

来断言T1T2类型是相同的。如果断言满足,该函数什么都不做。如果类型不同,函数调用将编译失败,编译器错误消息会说T1和T2不是同一类型,并且很可能(取决于编译器)显示给你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:

注意:当在类模板或函数模板的成员函数中使用时,StaticAssertTypeEq<T1, T2>()仅在函数实例化时有效。 例如,给定:

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:

不会生成编译器错误,因为Foo<bool>::Bar()实际上永远不会发生实例化。相反,你需要:

void Test2() { Foo<bool> foo; foo.Bar(); }

to cause a compiler error.

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’s 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" or "cannot initialize return object of type 'bool' with an rvalue of type 'void'" or "error: no viable conversion from 'void' to 'string'".

你可以在任何c++函数中使用断言。特别是,它不必是test fixture类的方法。有一个限制是,产生致命失败的断言(FAIL*ASSERT_*)只能在返回void的函数中使用。 这是谷歌不使用异常的结果。通过将它放在一个非void函数中,你会得到一个令人困惑的编译错误,比如"error: void value not ignored as it ought to "或"cannot initialize type of bool类型的返回对象为一个右值类型为void"error: no viable conversion from void to string "

If you need to use fatal 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的函数中使用致命断言,一种选择是让函数返回out参数的值。例如,你可以将T2 Foo(T1 x)重写为void Foo(T1 x, T2* result)。你需要确保即使函数过早返回,*result也包含一些合理的值。由于函数现在返回void,你可以在其中使用任何断言。

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_*.

如果不能更改函数的类型,你应该使用生成非致命失败的断言,例如ADD_FAILURE*EXPECT_*

{: .callout .note}
NOTE: Constructors and destructors are not considered void-returning unctions, 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. Instead, either call abort and crash the entire test executable, or put the fatal assertion in a SetUp/TearDown function; see constructor/destructor vs. SetUp/TearDown

注意: 根据c++语言规范,构造函数和析构函数不被认为是返回空值的函数,因此你不能在它们中使用致命断言;如果你尝试,会得到一个编译错误。 相反,要么调用abort并使整个测试可执行文件崩溃,要么将致命断言放在SetUp/TearDown函数中;参见[构造函数/析构函数vs.]“设置”/“拆卸”](faq.md # CtorVsSetUp)

{: .callout .warning}
WARNING: A fatal assertion in a helper function (private void-returning method) called from a constructor or destructor does not terminate the current test, as your intuition might suggest: it merely returns from the constructor or destructor early, possibly leaving your object in a partially-constructed or partially-destructed state! You almost certainly want to abort or use SetUp/TearDown instead.

警告:从构造函数或析构函数调用的辅助函数(返回void的私有方法)中的致命断言不会终止当前测试,正如你的直觉所暗示的那样:它只是从构造函数或析构函数中提前返回,可能会使对象处于部分构造或部分销毁的状态!!你几乎肯定想要使用abortSetUp/TearDown

Skipping test execution (跳过 test 执行)

Related to the assertions SUCCEED() and FAIL(), you can prevent further test execution at runtime with the GTEST_SKIP() macro. This is useful when you need to check for preconditions of the system under test during runtime and skip tests in a meaningful way.

与断言SUCCEED()FAIL()相关,你可以使用GTEST_SKIP()宏在运行时阻止进一步的测试执行。当您需要在运行时检查待测系统的先决条件并以一种有意义的方式跳过测试时,这很有用。

GTEST_SKIP() can be used in individual test cases or in the SetUp() methods of classes derived from either ::testing::Environment or ::testing::Test.

GTEST_SKIP()可以在单个测试用例中使用,也可以在派生自::testing::Environment::testing::test类的SetUp()方法中使用。

For example:

TEST(SkipTest, DoesSkip) {
  GTEST_SKIP() << "Skipping single test";
  EXPECT_EQ(0, 1);  // Won't fail; it won't be executed
}

class SkipFixture : public ::testing::Test {
 protected:
  void SetUp() override {
    GTEST_SKIP() << "Skipping all tests for this fixture";
  }
};

// Tests for SkipFixture won't be executed.
TEST_F(SkipFixture, SkipsOneTest) {
  EXPECT_EQ(5, 7);  // Won't fail
}

As with assertion macros, you can stream a custom message into GTEST_SKIP().

与断言宏一样,你可以将自定义消息流写入GTEST_SKIP()

Teaching GoogleTest How to Print Your Values (教 GoogleTest 如何打印你的值)

When a test assertion such as EXPECT_EQ fails, GoogleTest prints the argument values to help you debug. It does this using a user-extensible value printer.

当像EXPECT_EQ这样的测试断言失败时,GoogleTest会打印出参数值来帮助你调试。它使用一个用户可扩展的值打印机来实现这一点。

This printer knows how to print built-in C++ types, native arrays, STL containers, and any type that supports the << operator. For other types, it prints the raw bytes in the value and hopes that you the user can figure it out.

这个打印机知道如何打印内置c++类型、原生数组、STL容器以及任何支持<<运算符的类型。对于其他类型,它打印值中的原始字节,并希望你(用户)能够理解它。

As mentioned earlier, the printer is extensible. That means you can teach it to do a better job at printing your particular type than to dump the bytes. To do that, define an AbslStringify() overload as a friend function template for your type:

如前所述,打印机是 可扩展的。这意味着您可以教会它更好地打印您的特定类型,而不是转储字节。为此,为你的类型定义一个AbslStringify()重载函数作为friend函数模板:

namespace foo {

class Point {  // We want GoogleTest to be able to print instances of this.
  ...
  // Provide a friend overload.
  template <typename Sink>
  friend void AbslStringify(Sink& sink, const Point& point) {
    absl::Format(&sink, "(%d, %d)", point.x, point.y);
  }

  int x;
  int y;
};

// If you can't declare the function in the class it's important that the
// AbslStringify overload is defined in the SAME namespace that defines Point.
// C++'s look-up rules rely on that.
// 如果你不能在类中声明函数,那么使用
// AbslStringify重载函数与Point函数定义在同一个命名空间中。
// c++的查找规则依赖于它。

enum class EnumWithStringify { kMany = 0, kChoices = 1 };

template <typename Sink>
void AbslStringify(Sink& sink, EnumWithStringify e) {
  absl::Format(&sink, "%s", e == EnumWithStringify::kMany ? "Many" : "Choices");
}

}  // namespace foo

{: .callout .note}
Note: AbslStringify() utilizes a generic “sink” buffer to construct its string. For more information about supported operations on AbslStringify()'s sink, see go/abslstringify.

注意: AbslStringify()使用一个通用的“sink”缓冲区来构造它的字符串。 有关AbslStringify()接收器支持的操作的更多信息,请参见go/ AbslStringify。

AbslStringify() can also use absl::StrFormat’s catch-all %v type specifier within its own format strings to perform type deduction. Point above could be formatted as "(%v, %v)" for example, and deduce the int values as %d.

AbslStringify()也可以在自己的格式字符串中使用 absl::StrFormat的通用%v类型说明符来执行类型推断 。上面的Point可以格式化为"(%v, %v)",并推导出int的值为%d

Sometimes, AbslStringify() might not be an option: your team may wish to print types with extra debugging information for testing purposes only. If so, you can instead define a PrintTo() function like this:

有时,AbslStringify()可能不是一个选择:你的团队可能希望打印带有额外调试信息的类型,仅用于测试。如果是这样,你可以像下面这样定义一个PrintTo()函数:

#include <ostream>

namespace foo {

class Point {
  ...
  friend void PrintTo(const Point& point, std::ostream* os) {
    *os << "(" << point.x << "," << point.y << ")";
  }

  int x;
  int y;
};

// If you can't declare the function in the class it's important that PrintTo()
// is defined in the SAME namespace that defines Point.  C++'s look-up rules
// rely on that.
void PrintTo(const Point& point, std::ostream* os) {
    *os << "(" << point.x << "," << point.y << ")";
}

}  // namespace foo

If you have defined both AbslStringify() and PrintTo(), the latter will be used by GoogleTest. This allows you to customize how the value appears in GoogleTest’s output without affecting code that relies on the behavior of AbslStringify().

如果你定义了AbslStringify()PrintTo()PrintTo()将被GoogleTest使用。这允许你自定义值在GoogleTest输出中的显示方式,而不会影响依赖于AbslStringify()行为的代码。

If you have an existing << operator and would like to define an AbslStringify(), the latter will be used for GoogleTest printing.

如果你有一个现有的<<运算符,并且想要定义一个AbslStringify(),后者将用于GoogleTest打印。

If you want to print a value x using GoogleTest’s value printer yourself, just call ::testing::PrintToString(x), which returns an std::string:

如果你想用GoogleTest的值打印机打印出一个值x,只需调用 ::testing::PrintToString(x) ,它会返回一个std::string:

vector<pair<Point, int> > point_ints = GetPointIntVector();

EXPECT_TRUE(IsCorrectPointIntVector(point_ints))
    << "point_ints = " << testing::PrintToString(point_ints);

For more details regarding AbslStringify() and its integration with other
libraries, see go/abslstringify.

有关AbslStringify()及其与其他库集成的更多详细信息,请参见 go/AbslStringify。

Death Tests

In many applications, there are assertions that can cause application failure if a condition is not met. These consistency checks, which ensure that the program is in a known good state, are there to fail at the earliest possible time after some program state is corrupted. If the assertion checks the wrong condition, then the program may proceed in an erroneous state, which could lead to memory corruption, security holes, or worse. Hence it is vitally important to test that such assertion statements work as expected.

在许多应用程序中,如果某个条件不满足,断言可能导致应用程序失败。这些一致性检查确保程序处于已知的良好状态,在程序状态损坏后,尽早出现错误。如果断言检查了错误的条件,那么程序可能会继续处于错误的状态,这可能会导致内存损坏、安全漏洞,甚至更糟。因此,测试这种断言语句是否按预期工作至关重要。

Since these precondition checks cause the processes to die, we call such tests death tests. More generally, any test that checks that a program terminates (except by throwing an exception) in an expected fashion is also a death test.

因为这些前置条件检查会导致进程死亡,所以我们称这种测试为死亡测试。更一般地说,任何检查程序是否以预期方式终止(除非抛出异常)的测试也称为死亡测试。

Note that if a piece of code throws an exception, we don’t consider it “death” for the purpose of death tests, as the caller of the code could catch the exception and avoid the crash. If you want to verify exceptions thrown by your code, see Exception Assertions .

请注意,如果一段代码抛出异常,就死亡测试而言,我们不会认为它是“死亡”,因为代码的调用者可以捕获异常并避免崩溃。如果你想验证代码抛出的异常,请参阅Exception Assertions

If you want to test EXPECT_*()/ASSERT_*() failures in your test code, see “Catching” Failures.

如果你想测试 EXPECT_*()/ASSERT_*() 在测试代码中的失败,请参阅 catching-failures

How to Write a Death Test

GoogleTest provides assertion macros to support death tests. See Death Assertions in the Assertions Reference for details.

GoogleTest提供断言宏来支持死亡测试。有关详细信息,请参阅断言参考中的 Death Assertions

To write a death test, simply use one of the macros inside your test function. For example,

要编写死亡测试,只需使用测试函数中的一个宏。例如,

TEST(MyDeathTest, Foo) {
  // This death test uses a compound statement.
  ASSERT_DEATH({
    int n = 5;
    Foo(&n);
  }, "Error on line .* of Foo()");
}

TEST(MyDeathTest, NormalExit) {
  EXPECT_EXIT(NormalExit(), testing::ExitedWithCode(0), "Success");
}

TEST(MyDeathTest, KillProcess) {
  EXPECT_EXIT(KillProcess(), testing::KilledBySignal(SIGKILL),
              "Sending myself unblockable signal");
}

verifies that: 验证

  • calling Foo(5) causes the process to die with the given error message,
    调用Foo(5)会导致进程死亡,并给出错误信息,

  • calling NormalExit() causes the process to print "Success" to stderr and exit with exit code 0, and
    调用NormalExit()会导致进程将"Success"打印到stderr并以退出代码0退出

  • calling KillProcess() kills the process with signal SIGKILL.
    调用KillProcess()SIGKILL信号杀死进程。

The test function body may contain other assertions and statements as well, if necessary.

如果需要,测试函数体还可以包含其他断言和语句。

Note that a death test only cares about three things:

请注意,死亡测试只关心三件事:

  1. does statement abort or exit the process?

    statement会终止还是退出进程?

  2. (in the case of ASSERT_EXIT and EXPECT_EXIT) does the exit status satisfy predicate? Or (in the case of ASSERT_DEATH and EXPECT_DEATH) is the exit status non-zero? And

    (在ASSERT_EXITEXPECT_EXIT的例子中)退出状态满足predicate吗?或者(在ASSERT_DEATHEXPECT_DEATH的情况下)退出状态非零?和

  3. does the stderr output match matcher?

    stderr的输出是否匹配matcher?

In particular, if statement generates an ASSERT_* or EXPECT_* failure, it will not cause the death test to fail, as GoogleTest assertions don’t abort the process.

特别是,如果statement生成了ASSERT_*EXPECT_*失败,它将不会导致死亡测试失败,因为GoogleTest的断言不会中止进程。

Death Test Naming

{: .callout .important}
IMPORTANT: We strongly recommend you to follow the convention of naming your test suite (not test) *DeathTest when it contains a death test, as demonstrated in the above example. The Death Tests And Threads section below explains why.

重要:我们强烈建议你遵循命名你的 测试套件 的约定(而不是test) *DeathTest,当它包含死亡测试时,如上例所示。下面的死亡测试和线程部分解释了原因。

If a test fixture class is shared by normal tests and death tests, you can use using or typedef to introduce an alias for the fixture class and avoid duplicating its code:

如果一个测试夹具类被普通测试和死亡测试共享,你可以使用usingtypedef为夹具类引入别名,以避免重复代码:

class FooTest : public testing::Test { ... };

using FooDeathTest = FooTest;

TEST_F(FooTest, DoesThis) {
  // normal test
}

TEST_F(FooDeathTest, DoesThat) {
  // death test
}

Regular Expression Syntax 正则表达式语法

When built with Bazel and using Abseil, GoogleTest uses the RE2 syntax. Otherwise, for POSIX systems (Linux, Cygwin, Mac), GoogleTest uses the POSIX extended regular expression syntax. To learn about POSIX syntax, you may want to read this Wikipedia entry.

当使用Bazel和Abseil构建时,GoogleTest使用RE2语法。否则,对于POSIX系统(Linux、Cygwin、Mac), GoogleTest使用POSIX扩展正则表达式语法。要了解POSIX语法,你可能想阅读这个维基百科条目

On Windows, GoogleTest uses its own simple regular expression implementation. It lacks many features. For example, we don’t support union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and repetition count ( "x{5,7}"), among others. Below is what we do support (A denotes a literal character, period (.), or a single \\ escape sequence; x and y denote regular expressions.):

在Windows上,GoogleTest使用自己的简单正则表达式实现。它缺少很多功能。例如,我们不支持union ("x|y")、grouping ("(xy)")、brackets ("[xy]")和repeat count ("x{5,7}")等。下面是我们支持的内容(A 表示字面字符、句点(.)或单个\\转义序列;xy表示正则表达式。)

ExpressionMeaning
cmatches any literal character c
\\dmatches any decimal digit
\\Dmatches any character that’s not a decimal digit
\\fmatches \f
\\nmatches \n
\\rmatches \r
\\smatches any ASCII whitespace, including \n
\\Smatches any character that’s not a whitespace
\\tmatches \t
\\vmatches \v
\\wmatches any letter, _, or decimal digit
\\Wmatches any character that \\w doesn’t match
\\cmatches any literal character c, which must be a punctuation
.matches any single character except \n
A?matches 0 or 1 occurrences of A
A*matches 0 or many occurrences of A
A+matches 1 or many occurrences of A
^matches the beginning of a string (not that of each line)
$matches the end of a string (not that of each line)
xymatches x followed by y

To help you determine which capability is available on your system, GoogleTest defines macros to govern which regular expression it is using. The macros are: GTEST_USES_SIMPLE_RE=1 or GTEST_USES_POSIX_RE=1. If you want your death tests to work in all cases, you can either #if on these macros or use the more limited syntax only.

为了帮助您确定您的系统上有哪些功能,GoogleTest定义了宏来管理它正在使用的正则表达式。这些宏是:’ GTEST_USES_SIMPLE_RE=1 ‘或’ GTEST_USES_POSIX_RE=1 '。如果你希望你的死亡测试在所有情况下都能工作,你可以在这些宏上使用 #If,或者只使用更有限的语法。

How It Works

See Death Assertions in the Assertions Reference.

查看 Assertions Reference 中的 Death Assertions

Death Tests And Threads

The reason for the two death test styles has to do with thread safety. Due to well-known problems with forking in the presence of threads, death tests should be run in a single-threaded context. Sometimes, however, it isn’t feasible to arrange that kind of environment. For example, statically-initialized modules may start threads before main is ever reached. Once threads have been created, it may be difficult or impossible to clean them up.

两种死亡测试风格的原因与线程安全有关。由于众所周知的在线程存在时进行分支的问题,死亡测试应该在单线程上下文中运行。然而,有时安排这样的环境是不可行的。例如,静态初始化的模块可能在到达main之前就启动线程。一旦创建了线程,清理它们可能是困难的或不可能的。

GoogleTest has three features intended to raise awareness of threading issues.

GoogleTest有三个功能旨在提高对线程问题的认识。

  1. A warning is emitted if multiple threads are running when a death test is encountered.

    当遇到死亡测试时,如果多个线程正在运行,则会发出警告。

  2. Test suites with a name ending in “DeathTest” are run before all other tests.

    名称以"DeathTest"结尾的测试套件会在所有其他测试之前运行。

  3. It uses clone() instead of fork() to spawn the child process on Linux (clone() is not available on Cygwin and Mac), as fork() is more likely to cause the child to hang when the parent process has multiple threads.

    它使用clone()而不是fork()来在Linux上派生子进程(clone()在Cygwin和Mac上不可用),因为当父进程有多个线程时,fork()更有可能导致子进程挂起。

It’s perfectly fine to create threads inside a death test statement; they are executed in a separate process and cannot affect the parent.

在死亡测试语句中创建线程完全没问题;它们在单独的进程中执行,不会影响父进程。

Death Test Styles

The “threadsafe” death test style was introduced in order to help mitigate the risks of testing in a possibly multithreaded environment. It trades increased test execution time (potentially dramatically so) for improved thread safety.

“线程安全”死亡测试风格的引入是为了帮助降低在可能是多线程的环境中进行测试的风险。它以增加测试执行时间(可能会显著增加)换取改进的线程安全性。

The automated testing framework does not set the style flag. You can choose a particular style of death tests by setting the flag programmatically:

自动化测试框架不会设置style标志。你可以通过编程方式设置标志来选择特定的死亡测试样式:

GTEST_FLAG_SET(death_test_style, "threadsafe");

You can do this in main() to set the style for all death tests in the binary, or in individual tests. Recall that flags are saved before running each test and restored afterwards, so you need not do that yourself. For example:

**你可以在main()中为二进制文件中的所有死亡测试设置样式,或者在单个测试中设置样式。**回想一下,标志在运行每个测试之前被保存,并在之后被恢复,所以您不需要自己做这些。例如:

int main(int argc, char** argv) {
  testing::InitGoogleTest(&argc, argv);
  GTEST_FLAG_SET(death_test_style, "fast");
  return RUN_ALL_TESTS();
}

TEST(MyDeathTest, TestOne) {
  GTEST_FLAG_SET(death_test_style, "threadsafe");
  // This test is run in the "threadsafe" style:
  ASSERT_DEATH(ThisShouldDie(), "");
}

TEST(MyDeathTest, TestTwo) {
  // This test is run in the "fast" style:
  ASSERT_DEATH(ThisShouldDie(), "");
}

Caveats / 警告

The statement argument of ASSERT_EXIT() can be any valid C++ statement. If it leaves the current function via a return statement or by throwing an exception, the death test is considered to have failed. Some GoogleTest macros may return from the current function (e.g. ASSERT_TRUE()), so be sure to avoid them in statement.

ASSERT_EXIT()statement参数可以是任何有效的c++语句。如果它通过return语句或抛出异常离开当前函数,则认为死亡测试失败。一些GoogleTest宏可能从当前函数返回(例如:ASSERT_TRUE()),所以一定要避免在statement中使用它们。

Since statement runs in the child process, any in-memory side effect (e.g. modifying a variable, releasing memory, etc) it causes will not be observable in the parent process. In particular, if you release memory in a death test, your program will fail the heap check as the parent process will never see the memory reclaimed. To solve this problem, you can

由于statement在子进程中运行,它导致的任何内存中的副作用(例如修改变量、释放内存等)在父进程中不会被观察到。特别是,如果在死亡测试中释放内存,程序的堆检查将失败,因为父进程永远不会看到内存被回收。要解决这个问题,你可以

  1. try not to free memory in a death test;

    在死亡测试中尽量不要释放内存;

  2. free the memory again in the parent process; or

    在父进程中再次释放内存。或

  3. do not use the heap checker in your program.

    不要在程序中使用堆检查器。

Due to an implementation detail, you cannot place multiple death test assertions on the same line; otherwise, compilation will fail with an unobvious error message.

由于实现细节的原因,您不能将多个死亡测试断言放在同一行;否则,编译将失败,并显示不明显的错误消息。

Despite the improved thread safety afforded by the “threadsafe” style of death test, thread problems such as deadlock are still possible in the presence of handlers registered with pthread_atfork(3).

尽管“线程安全”风格的死亡测试提供了改进的线程安全性,但在使用 pthread_atfork(3) 注册的处理程序时,仍然可能出现死锁等线程问题。

Using Assertions in Sub-routines / 在子例程中使用断言

{: .callout .note}
Note: If you want to put a series of test assertions in a subroutine to check for a complex condition, consider using a custom GMock matcher instead. This lets you provide a more readable error message in case of failure and avoid all of the issues described below.

注意:如果您想在子例程中放置一系列测试断言以检查复杂的条件,请考虑使用 a custom GMock matcher。这使您可以在失败时提供更可读的错误消息,并避免下面描述的所有问题。

Adding Traces to Assertions / 向断言添加跟踪

If a test sub-routine is called from several places, when an assertion inside it fails, it can be hard to tell which invocation of the sub-routine the failure is from. You can alleviate this problem using extra logging or custom failure messages, but that usually clutters up your tests. A better solution is to use the SCOPED_TRACE macro or the ScopedTrace utility:

如果从多个地方调用测试子例程,当其中的断言失败时,很难判断失败的子例程来自哪个调用。您可以使用额外的日志记录或自定义失败消息来缓解这个问题,但这通常会使您的测试变得混乱。更好的解决方案是使用SCOPED_TRACE宏或者ScopedTrace工具:

SCOPED_TRACE(message);
ScopedTrace trace("file_path", line_number, message);

where message can be anything streamable to std::ostream. SCOPED_TRACE macro will cause the current file name, line number, and the given message to be added in every failure message. ScopedTrace accepts explicit file name and line number in arguments, which is useful for writing test helpers. The effect will be undone when the control leaves the current lexical scope.

其中message可以是任何可以写入std::ostream的流。SCOPED_TRACE宏将导致当前文件名、行号和给定消息被添加到每个失败消息中。ScopedTrace接受显式的文件名和行号作为参数,这对于编写测试辅助函数很有用。当控件离开当前词法作用域时,该效果将被撤销。

For example,

10: void Sub1(int n) {
11:   EXPECT_EQ(Bar(n), 1);
12:   EXPECT_EQ(Bar(n + 1), 2);
13: }
14:
15: TEST(FooTest, Bar) {
16:   {
17:     SCOPED_TRACE("A");  // This trace point will be included in
18:                         // every failure in this scope.
19:     Sub1(1);
20:   }
21:   // Now it won't.
22:   Sub1(9);
23: }

could result in messages like these:

可能会得到这样的消息:

path/to/foo_test.cc:11: Failure
Value of: Bar(n)
Expected: 1
  Actual: 2
Google Test trace:
path/to/foo_test.cc:17: A

path/to/foo_test.cc:12: Failure
Value of: Bar(n + 1)
Expected: 2
  Actual: 3

Without the trace, it would’ve been difficult to know which invocation of Sub1() the two failures come from respectively. (You could add an extra message to each assertion in Sub1() to indicate the value of n, but that’s tedious.)

如果没有跟踪,就很难知道这两个失败分别来自于对Sub1()的哪个调用。(你可以在Sub1()中的每个断言中添加一条额外的消息来表示n的值,但这很乏味。)

Some tips on using SCOPED_TRACE:

使用SCOPED TRACE的一些提示:

  1. With a suitable message, it’s often enough to use SCOPED_TRACE at the beginning of a sub-routine, instead of at each call site.

    有了合适的消息,通常在子例程的开始使用SCOPED_TRACE就足够了,而不是在每个调用点使用。

  2. When calling sub-routines inside a loop, make the loop iterator part of the message in SCOPED_TRACE such that you can know which iteration the failure is from.

    当在循环内调用子例程时,将循环迭代器作为SCOPED_TRACE消息的一部分,这样你就可以知道失败来自哪个迭代。

  3. Sometimes the line number of the trace point is enough for identifying the particular invocation of a sub-routine. In this case, you don’t have to choose a unique message for SCOPED_TRACE. You can simply use "".

    有时,跟踪点的行号就足以标识子例程的特定调用。在这种情况下,你不必为SCOPED_TRACE选择唯一的消息。你可以简单地使用""

  4. You can use SCOPED_TRACE in an inner scope when there is one in the outer scope. In this case, all active trace points will be included in the failure messages, in reverse order they are encountered.

    当外部作用域中有SCOPED_TRACE时,你可以在内部作用域中使用它。在这种情况下,所有活动跟踪点都将包含在失败消息中,顺序与遇到它们的顺序相反。

  5. The trace dump is clickable in Emacs - hit return on a line number and you’ll be taken to that line in the source file!

    在Emacs中可以点击跟踪转储——点击行号上的return,你将被带到源文件中的那一行!

Propagating Fatal Failures / 传播致命故障

A common pitfall when using ASSERT_* and FAIL* is not understanding that when they fail they only abort the current function, not the entire test. For example, the following test will segfault:

使用ASSERT_*FAIL*时的一个常见陷阱是不明白当它们失败时,它们只中止当前函数,而不是终止整个测试。例如,下面的测试将执行segfault:

void Subroutine() {
  // Generates a fatal failure and aborts the current function.
  ASSERT_EQ(1, 2);

  // The following won't be executed.
  ...
}

TEST(FooTest, Bar) {
  Subroutine();  // The intended behavior is for the fatal failure
                 // in Subroutine() to abort the entire test.

  // The actual behavior: the function goes on after Subroutine() returns.
  int* p = nullptr;
  *p = 3;  // Segfault!
}

To alleviate this, GoogleTest provides three different solutions. You could use either exceptions, the (ASSERT|EXPECT)_NO_FATAL_FAILURE assertions or the HasFatalFailure() function. They are described in the following two subsections.

为了缓解这个问题,GoogleTest提供了三种不同的解决方案。你可以使用任何异常,(ASSERT|EXPECT)_NO_FATAL_FAILURE断言或HasFatalFailure()函数。它们将在以下两个小节中描述。

Asserting on Subroutines with an exception / 在有异常的子程序上断言

The following code can turn ASSERT-failure into an exception:

下列代码可以将ASSERT-failure转换为异常:

class ThrowListener : public testing::EmptyTestEventListener {
  void OnTestPartResult(const testing::TestPartResult& result) override {
    if (result.type() == testing::TestPartResult::kFatalFailure) {
      throw testing::AssertionException(result);
    }
  }
};
int main(int argc, char** argv) {
  ...
  testing::UnitTest::GetInstance()->listeners().Append(new ThrowListener);
  return RUN_ALL_TESTS();
}

This listener should be added after other listeners if you have any, otherwise they won’t see failed OnTestPartResult.

如果你有其他监听器,这个监听器应该添加在其他监听器之后,否则它们不会看到失败的OnTestPartResult

Asserting on Subroutines / 在子程序上断言

As shown above, if your test calls a subroutine that has an ASSERT_* failure in it, the test will continue after the subroutine returns. This may not be what you want.

如上所示,如果你的测试调用了一个ASSERT_*失败的子例程,那么在子例程返回后,测试将继续。这可能不是你想要的。

Often people want fatal failures to propagate like exceptions. For that GoogleTest offers the following macros:

人们通常希望致命故障像异常一样传播。为此,GoogleTest提供了以下宏:

Fatal assertionNonfatal assertionVerifies
ASSERT_NO_FATAL_FAILURE(statement);EXPECT_NO_FATAL_FAILURE(statement);statement

doesn’t generate any new fatal failures in the current thread.

不会在当前线程中产生任何新的致命错误。

Only failures in the thread that executes the assertion are checked to determine the result of this type of assertions. If statement creates new threads, failures in these threads are ignored.

只有执行断言的线程中的故障才会被检查,以确定这种类型断言的结果。如果statement创建了新的线程,这些线程中的失败将被忽略。

Examples:

ASSERT_NO_FATAL_FAILURE(Foo());

int i;
EXPECT_NO_FATAL_FAILURE({
  i = Bar();
});

Assertions from multiple threads are currently not supported on Windows.

Windows目前不支持多线程中的断言。

Checking for Failures in the Current Test / 检查当前测试中的失败

HasFatalFailure() in the ::testing::Test class returns true if an assertion in the current test has suffered a fatal failure. This allows functions to catch fatal failures in a sub-routine and return early.

如果当前测试中的断言发生了致命失败,::testing::Test类中的HasFatalFailure()会返回true。这允许函数捕获子例程中的致命故障并提前返回。

class Test {
 public:
  ...
  static bool HasFatalFailure();
};

The typical usage, which basically simulates the behavior of a thrown exception,is:

典型的用法基本上是模拟抛出异常的行为,

TEST(FooTest, Bar) {
  Subroutine();
  // Aborts if Subroutine() had a fatal failure.
  if (HasFatalFailure()) return;

  // The following won't be executed.
  ...
}

If HasFatalFailure() is used outside of TEST() , TEST_F() , or a test fixture, you must add the ::testing::Test:: prefix, as in:

如果HasFatalFailure()TEST()TEST_F()或测试夹具之外使用,则必须添加::testing:: TEST::前缀,例如:

if (testing::Test::HasFatalFailure()) return;

Similarly, HasNonfatalFailure() returns true if the current test has at least one non-fatal failure, and HasFailure() returns true if the current test has at least one failure of either kind.

类似地,如果当前测试至少有一个非致命失败,HasNonfatalFailure()返回true,如果当前测试至少有一个非致命失败,HasFailure()返回true

Logging Additional Information

In your test code, you can call RecordProperty("key", value) to log additional information, where value can be either a string or an int. The last value recorded for a key will be emitted to the XML output if you specify one. For example, the test

在你的测试代码中,你可以调用RecordProperty("key", value)来记录额外的信息,其中value可以是字符串或int。如果你指定了[XML输出](# generated -an- XML -report),那么为键记录的最后值将被发送到它。 例如,测试

TEST_F(WidgetUsageTest, MinAndMaxWidgets) {
  RecordProperty("MaximumWidgets", ComputeMaxUsage());
  RecordProperty("MinimumWidgets", ComputeMinUsage());
}

will output XML like this:

  ...
    <testcase name="MinAndMaxWidgets" file="test.cpp" line="1" status="run" time="0.006" classname="WidgetUsageTest" MaximumWidgets="12" MinimumWidgets="9" />
  ...

{: .callout .note}

NOTE:

  • RecordProperty() is a static member of the Test class. Therefore it
    needs to be prefixed with ::testing::Test:: if used outside of the
    TEST body and the test fixture class.

RecordProperty()Test类的静态成员。因此,如果在外部使用,>需要以::testing::Test::作为前缀 TEST主体和测试夹具类。

  • key must be a valid XML attribute name, and cannot conflict with the

    ones already used by GoogleTest (name, status, time, classname,
    type_param, and value_param).

*key*必须是一个有效的XML属性名,并且不能与已经被GoogleTest使用的> (namestatustimeclassnametype_paramvalue_param)。

  • Calling RecordProperty() outside of the lifespan of a test is allowed.
    If it’s called outside of a test but between a test suite’s
    SetUpTestSuite() and TearDownTestSuite() methods, it will be
    attributed to the XML element for the test suite. If it’s called outside
    of all test suites (e.g. in a test environment), it will be attributed to
    the top-level XML element.
  • 允许在测试生命周期之外调用RecordProperty()。如果在测试之外,在测试套件的SetUpTestSuite()TearDownTestSuite()方法之间调用它,它将归属于测试套件的XML元素。如果在所有测试套件之外(例如在测试环境中)调用它,它将被赋值为顶级XML元素。

Sharing Resources Between Tests in the Same Test Suite / 在同一测试套件中的测试之间共享资源

GoogleTest creates a new test fixture object for each test in order to make tests independent and easier to debug. However, sometimes tests use resources that are expensive to set up, making the one-copy-per-test model prohibitively expensive.

GoogleTest为每个测试创建一个新的测试夹具对象,以使测试独立且更容易调试。然而,有时测试使用的资源设置成本很高,这使得每个测试一份的模式变得非常昂贵。

If the tests don’t change the resource, there’s no harm in their sharing a single resource copy. So, in addition to per-test set-up/tear-down, GoogleTest also supports per-test-suite set-up/tear-down. To use it:

如果测试没有改变资源,那么共享一个资源副本也没有什么坏处。因此,除了每个测试的设置/删除,GoogleTest也支持每个测试套件的设置/删除。使用方法:

  1. In your test fixture class (say FooTest ), declare as static some member variables to hold the shared resources.

    在你的测试夹具类(比如FooTest)中,将一些成员变量声明为static来保存共享资源。

  2. Outside your test fixture class (typically just below it), define those member variables, optionally giving them initial values.

    在您的测试夹具类之外(通常就在它下面),定义这些成员变量,可选地为它们提供初始值。

  3. In the same test fixture class, define a static void SetUpTestSuite() function (remember not to spell it as SetupTestSuite with a small u!) to set up the shared resources and a static void TearDownTestSuite() function to tear them down.

    在同一个测试夹具类中,定义一个static void SetUpTestSuite()函数(记住不要将它拼写为带有小u的**SetUpTestSuite**)来设置共享资源,并定义一个static void TearDownTestSuite()函数来删除它们。

That’s it! GoogleTest automatically calls SetUpTestSuite() before running the first test in the FooTest test suite (i.e. before creating the first FooTest object), and calls TearDownTestSuite() after running the last test in it (i.e. after deleting the last FooTest object). In between, the tests can use the shared resources.

就是这样!GoogleTest在运行FooTest测试套件中的第一个测试之前(即在创建第一个FooTest对象之前)自动调用SetUpTestSuite(),并在运行其中的最后一个测试后(即在删除最后一个FooTest对象之后)调用TearDownTestSuite()。在这两者之间,测试可以使用共享资源。

Remember that the test order is undefined, so your code can’t depend on a test preceding or following another. Also, the tests must either not modify the state of any shared resource, or, if they do modify the state, they must restore the state to its original value before passing control to the next test.

请记住,测试顺序是未定义的,因此你的代码不能依赖于测试的前后。此外,测试必须不修改任何共享资源的状态,或者,如果它们修改了状态,则必须在将控制权传递给下一个测试之前将状态恢复到其原始值。

Note that SetUpTestSuite() may be called multiple times for a test fixture class that has derived classes, so you should not expect code in the function body to be run only once. Also, derived classes still have access to shared resources defined as static members, so careful consideration is needed when managing shared resources to avoid memory leaks if shared resources are not properly cleaned up in TearDownTestSuite().

请注意,对于具有派生类的测试fixture类,SetUpTestSuite()可能会被调用多次,因此你不应该期望函数体中的代码只运行一次。此外,派生类仍然可以访问定义为静态成员的共享资源,因此在管理共享资源时需要仔细考虑,以避免在TearDownTestSuite()中没有正确清理共享资源时发生内存泄漏。

Here’s an example of per-test-suite set-up and tear-down:

下面是每个测试套件的set-up和tear-down例子:

class FooTest : public testing::Test {
 protected:
  // Per-test-suite set-up.
  // Called before the first test in this test suite.
  // Can be omitted if not needed.
  static void SetUpTestSuite() {
    shared_resource_ = new ...;

    // If `shared_resource_` is **not deleted** in `TearDownTestSuite()`,
    // reallocation should be prevented because `SetUpTestSuite()` may be called
    // in subclasses of FooTest and lead to memory leak.
    //
    // if (shared_resource_ == nullptr) {
    //   shared_resource_ = new ...;
    // }
  }

  // Per-test-suite tear-down.
  // Called after the last test in this test suite.
  // Can be omitted if not needed.
  static void TearDownTestSuite() {
    delete shared_resource_;
    shared_resource_ = nullptr;
  }

  // You can define per-test set-up logic as usual.
  void SetUp() override { ... }

  // You can define per-test tear-down logic as usual.
  void TearDown() override { ... }

  // Some expensive resource shared by all tests.
  static T* shared_resource_;
};

T* FooTest::shared_resource_ = nullptr;

TEST_F(FooTest, Test1) {
  ... you can refer to shared_resource_ here ...
}

TEST_F(FooTest, Test2) {
  ... you can refer to shared_resource_ here ...
}

{: .callout .note}
NOTE: Though the above code declares SetUpTestSuite() protected, it may sometimes be necessary to declare it public, such as when using it with TEST_P.

注意:尽管上面的代码将SetUpTestSuite()声明为protected,但有时可能需要将其声明为public,例如在与TEST_P一起使用时。

Global Set-Up and Tear-Down

Just as you can do set-up and tear-down at the test level and the test suite level, you can also do it at the test program level. Here’s how.

正如您可以在测试级别和测试套件级别进行设置和拆除一样,您也可以在测试程序级别进行设置和拆除。这是如何。

First, you subclass the ::testing::Environment class to define a test environment, which knows how to set-up and tear-down:

首先,继承::testing::Environment类来定义一个测试环境,它知道如何设置和删除:

class Environment : public ::testing::Environment {
 public:
  ~Environment() override {}

  // Override this to define how to set up the environment.
  void SetUp() override {}

  // Override this to define how to tear down the environment.
  void TearDown() override {}
};

Then, you register an instance of your environment class with GoogleTest by calling the ::testing::AddGlobalTestEnvironment() function:

然后,通过调用 ::testing::AddGlobalTestEnvironment()函数在GoogleTest中注册一个环境类的实例:

Environment* AddGlobalTestEnvironment(Environment* env);

Now, when RUN_ALL_TESTS() is called, it first calls the SetUp() method of each environment object, then runs the tests if none of the environments reported fatal failures and GTEST_SKIP() was not called. RUN_ALL_TESTS() always calls TearDown() with each environment object, regardless of whether or not the tests were run.

现在,当调用RUN_ALL_TESTS()时,它首先调用每个环境对象的SetUp()方法,然后在没有报告致命故障且没有调用GTEST_SKIP()的环境中运行测试。RUN_ALL_TESTS()总是对每个环境对象调用TearDown(),无论测试是否运行。

It’s OK to register multiple environment objects. In this suite, their SetUp() will be called in the order they are registered, and their TearDown() will be called in the reverse order.

可以注册多个环境对象。在这个套件中,他们的SetUp()将按注册的顺序被调用,而他们的TearDown()将按相反的顺序被调用。
Note that GoogleTest takes ownership of the registered environment objects. Therefore do not delete them by yourself.
请注意,GoogleTest获取注册的环境对象的所有权。因此,不要自行删除它们

You should call AddGlobalTestEnvironment() before RUN_ALL_TESTS() is called, probably in main(). If you use gtest_main, you need to call this before main() starts for it to take effect. One way to do this is to define a global variable like this:

你应该在调用RUN_ALL_TESTS()之前调用AddGlobalTestEnvironment(),可能是在main()中。如果你使用gtest_main,你需要在main()开始之前调用它才能生效。一种方法是像这样定义一个全局变量:

testing::Environment* const foo_env =
    testing::AddGlobalTestEnvironment(new FooEnvironment);

However, we strongly recommend you to write your own main() and call AddGlobalTestEnvironment() there, as relying on initialization of global variables makes the code harder to read and may cause problems when you register multiple environments from different translation units and the environments have dependencies among them (remember that the compiler doesn’t guarantee the order in which global variables from different translation units are initialized).

然而,我们强烈建议你编写自己的main()并在其中调用AddGlobalTestEnvironment() 因为依赖于全局变量的初始化会使代码更难阅读,并且当你注册来自不同翻译单元的多个环境并且这些环境之间存在依赖关系时,可能会导致问题(请记住,编译器并不保证来自不同翻译单元的全局变量初始化的顺序)。

Value-Parameterized Tests

Value-parameterized tests allow you to test your code with different parameters without writing multiple copies of the same test. This is useful in a number of situations, for example:

值参数化测试允许你使用不同的参数来测试你的代码,而无需编写相同测试的多个副本。这在很多情况下都很有用,例如:

  • You have a piece of code whose behavior is affected by one or more
    command-line flags. You want to make sure your code performs correctly for
    various values of those flags.

    你有一段代码,它的行为会受到一个或多个命令行标志的影响。你希望确保代码对这些标志的不同值都能正确执行。

  • You want to test different implementations of an OO interface.

    您想测试面向对象接口的不同实现。

  • You want to test your code over various inputs (a.k.a. data-driven testing).
    This feature is easy to abuse, so please exercise your good sense when doing
    it!

    你想在不同的输入上测试你的代码(也就是数据驱动测试)。这个功能很容易被滥用,所以请在使用时发挥你的判断力!

How to Write Value-Parameterized Tests

如何编写值参数化测试

To write value-parameterized tests, first you should define a fixture class. It must be derived from both testing::Test and testing::WithParamInterface<T> (the latter is a pure interface), where T is the type of your parameter values. For convenience, you can just derive the fixture class from testing::TestWithParam<T>, which itself is derived from both testing::Test and testing::WithParamInterface<T>. T can be any copyable type. If it’s a raw pointer, you are responsible for managing the lifespan of the pointed values.

要编写值参数化测试,首先应该定义一个fixture类。它必须从testing::Testtesting::WithParamInterface<T>(后者是一个纯接口)派生,其中T是参数值的类型。为了方便,你可以从testing::TestWithParam<T>派生出fixture类,它本身是由testing::Testtesting::WithParamInterface<T>派生的。T可以是任何可复制类型。如果它是一个原始指针,则您负责管理指向值的生命周期。

{: .callout .note}

NOTE: If your test fixture defines SetUpTestSuite() or TearDownTestSuite() they must be declared public rather than protected in order to use TEST_P.
注意:如果你的测试 fixture 定义了 SetUpTestSuite()TearDownTestSuite()为了使用TEST_P,它们必须被声明为 public 而不是 protected

class FooTest :
    public testing::TestWithParam<const char*> {
  // You can implement all the usual fixture class members here.
  // To access the test parameter, call GetParam() from class
  // TestWithParam<T>.
};

// Or, when you want to add parameters to a pre-existing fixture class:
class BaseTest : public testing::Test {
  ...
};
class BarTest : public BaseTest,
                public testing::WithParamInterface<const char*> {
  ...
};

Then, use the TEST_P macro to define as many test patterns using this fixture as you want. The _P suffix is for “parameterized” or “pattern”, whichever you prefer to think.

然后,使用TEST_P宏使用这个fixture定义尽可能多的测试模式。后缀_P代表“参数化”或“模式”,随你怎么想。

TEST_P(FooTest, DoesBlah) {
  // Inside a test, access the test parameter with the GetParam() method
  // of the TestWithParam<T> class:
  EXPECT_TRUE(foo.Blah(GetParam()));
  ...
}

TEST_P(FooTest, HasBlahBlah) {
  ...
}

Finally, you can use the INSTANTIATE_TEST_SUITE_P macro to instantiate the test suite with any set of parameters you want. GoogleTest defines a number of functions for generating test parameters—see details atINSTANTIATE_TEST_SUITE_P in the Testing Reference.

最后,你可以使用INSTANTIATE_TEST_SUITE_P宏使用任何你想要的参数集来实例化测试套件。GoogleTest定义了许多用于生成测试参数的函数,详情参见测试参考中的’ INSTANTIATE_TEST_SUITE_P '

For example, the following statement will instantiate tests from the FooTest test suite each with parameter values "meeny", "miny", and "moe" using the Values parameter generator:

例如,下面的语句将使用参数生成器’values’实例化FooTest测试套件中的每个带有参数值"meeny""miny""moe"的测试:

INSTANTIATE_TEST_SUITE_P(MeenyMinyMoe,
                         FooTest,
                         testing::Values("meeny", "miny", "moe"));

{: .callout .note}
NOTE: The code above must be placed at global or namespace scope, not at function scope.

注意:上面的代码必须放在全局或命名空间作用域中,而不是函数作用域中。

The first argument to INSTANTIATE_TEST_SUITE_P is a unique name for the instantiation of the test suite. The next argument is the name of the test pattern, and the last is the parameter generator.

INSTANTIATE_TEST_SUITE_P的第一个参数是用于实例化测试套件的唯一名称。下一个参数是测试模式的名称,最后一个是参数生成器

The parameter generator expression is not evaluated until GoogleTest is initialized (via InitGoogleTest()). Any prior initialization done in the main function will be accessible from the parameter generator, for example, the results of flag parsing.

在初始化GoogleTest(通过InitGoogleTest())之前,参数生成器表达式不会被求值。任何之前在main函数中完成的初始化都可以从参数生成器中访问,例如,标志解析的结果。

You can instantiate a test pattern more than once, so to distinguish different instances of the pattern, the instantiation name is added as a prefix to the actual test suite name. Remember to pick unique prefixes for different instantiations. The tests from the instantiation above will have these names:

您可以多次实例化一个测试模式,因此为了区分模式的不同实例,实例化名称作为实际测试套件名称的前缀被添加。记住为不同的实例化选择唯一的前缀。上面实例化的测试名称如下:

  • MeenyMinyMoe/FooTest.DoesBlah/0 for "meeny"
  • MeenyMinyMoe/FooTest.DoesBlah/1 for "miny"
  • MeenyMinyMoe/FooTest.DoesBlah/2 for "moe"
  • MeenyMinyMoe/FooTest.HasBlahBlah/0 for "meeny"
  • MeenyMinyMoe/FooTest.HasBlahBlah/1 for "miny"
  • MeenyMinyMoe/FooTest.HasBlahBlah/2 for "moe"

You can use these names in --gtest_filter.

你可以在’——gtest_filter '中使用这些名称。

The following statement will instantiate all tests from FooTest again, each with parameter values "cat" and "dog" using the ValuesIn parameter generator:

下面的语句将再次实例化FooTest中的所有测试,每个测试都具有参数值"cat""dog",使用参数生成器ValuesIn:

const char* pets[] = {"cat", "dog"};
INSTANTIATE_TEST_SUITE_P(Pets, FooTest, testing::ValuesIn(pets));

The tests from the instantiation above will have these names:

上面实例化的测试名称如下:

  • Pets/FooTest.DoesBlah/0 for "cat"
  • Pets/FooTest.DoesBlah/1 for "dog"
  • Pets/FooTest.HasBlahBlah/0 for "cat"
  • Pets/FooTest.HasBlahBlah/1 for "dog"

Please note that INSTANTIATE_TEST_SUITE_P will instantiate all tests in the given test suite, whether their definitions come before or after the INSTANTIATE_TEST_SUITE_P statement.

请注意,INSTANTIATE_TEST_SUITE_P将实例化给定测试套件中的所有测试,无论它们的定义是在INSTANTIATE_TEST_SUITE_P语句之前还是之后

Additionally, by default, every TEST_P without a corresponding INSTANTIATE_TEST_SUITE_P causes a failing test in test suite GoogleTestVerification. If you have a test suite where that omission is not an error, for example it is in a library that may be linked in for other reasons or where the list of test cases is dynamic and may be empty, then this check can be suppressed by tagging the test suite:

此外,默认情况下,每个没有对应的TEST_P实例化_test_suite_p TEST_P都会导致GoogleTestVerification`测试失败。 如果你有一个测试套件,其中的遗漏不是一个错误,例如它在一个可能由于其他原因被链接的库中,或者测试用例列表是动态的,可能是空的,那么这个检查可以通过标记测试套件来抑制:

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FooTest);

You can see [sample7_unittest.cc] and [sample8_unittest.cc] for more examples.

Creating Value-Parameterized Abstract Tests / 创建值参数化的抽象测试

In the above, we define and instantiate FooTest in the same source file.Sometimes you may want to define value-parameterized tests in a library and let other people instantiate them later. This pattern is known as abstract tests.

在上面的代码中,我们在同一个源文件中定义并实例化了FooTest。有时,你可能想在库中定义值参数化的测试,然后让其他人实例化它们。这种模式被称为抽象测试

As an example of its application, when you are designing an interface you can write a standard suite of abstract tests (perhaps using a factory function as the test parameter) that all implementations of the interface are expected to pass. When someone implements the interface, they can instantiate your suite to get all the interface-conformance tests for free.

作为一个应用的例子,当你设计一个接口时,你可以编写一套标准的抽象测试(也许使用一个工厂函数作为测试参数),接口的所有实现都应该通过这些测试。当有人实现接口时,他们可以实例化你的套件来免费获得所有接口一致性测试。

To define abstract tests, you should organize your code like this:

要定义抽象测试,你应该像这样组织代码:

  1. Put the definition of the parameterized test fixture class (e.g. FooTest) in a header file, say foo_param_test.h. Think of this as declaring your abstract tests.

    将参数化测试夹具类的定义(例如:在头文件FooTest中,写foo_param_test.h。可以把它想象成声明你的抽象测试。

  2. Put the TEST_P definitions in foo_param_test.cc, which includes foo_param_test.h. Think of this as implementing your abstract tests.

    TEST_P的定义放在foo_param_test. py文件中。其中包含foo_param_test.h。可以把它看作是实现你的抽象测试。

Once they are defined, you can instantiate them by including foo_param_test.h,invoking INSTANTIATE_TEST_SUITE_P(), and depending on the library target that contains foo_param_test.cc. You can instantiate the same abstract test suite multiple times, possibly in different source files.

一旦定义了它们,你可以通过包含foo_param_test.h来实例化它们,调用INSTANTIATE_TEST_SUITE_P(),这取决于包含foo_param_test.cc的库目标。您可以多次实例化相同的抽象测试套件,可能在不同的源文件中。

Specifying Names for Value-Parameterized Test Parameters / 为值参数化的测试参数指定名称

The optional last argument to INSTANTIATE_TEST_SUITE_P() allows the user to specify a function or functor that generates custom test name suffixes based on the test parameters. The function should accept one argument of type testing::TestParamInfo<class ParamType> , and return std::string.

INSTANTIATE_TEST_SUITE_P()的最后一个可选参数允许用户指定一个函数或函子,根据测试参数生成自定义测试名称后缀。这个函数应该接受一个类型为 testing::TestParamInfo<class ParamType> 的参数,并返回std::string

testing::PrintToStringParamName is a builtin test suffix generator that returns the value of testing::PrintToString(GetParam()). It does not work for std::string or C strings.

testing::PrintToStringParamName是一个内置的测试后缀生成器,它返回testing::PrintToString(GetParam())的值。它不适用于std::string或C字符串。

{: .callout .note}
NOTE: test names must be non-empty, unique, and may only contain ASCII alphanumeric characters. In particular, they should not contain underscores

注意:测试名称必须是非空的,唯一的,并且只能包含ASCII字母数字字符。特别是,它们不应该包含下划线

class MyTestSuite : public testing::TestWithParam<int> {};

TEST_P(MyTestSuite, MyTest)
{
  std::cout << "Example Test Param: " << GetParam() << std::endl;
}

INSTANTIATE_TEST_SUITE_P(MyGroup, MyTestSuite, testing::Range(0, 10),
                         testing::PrintToStringParamName());

Providing a custom functor allows for more control over test parameter name generation, especially for types where the automatic conversion does not generate helpful parameter names (e.g. strings as demonstrated above). The following example illustrates this for multiple parameters, an enumeration type and a string, and also demonstrates how to combine generators. It uses a lambda for conciseness:

提供一个自定义的functor允许对测试参数名的生成有更多的控制,特别是对于自动转换没有生成有用参数名的类型(例如上面演示的字符串)。 下面的示例演示了如何对多个参数、枚举类型和字符串进行此操作,并演示了如何组合生成器。为了简洁,它使用了lambda表达式:

enum class MyType { MY_FOO = 0, MY_BAR = 1 };

class MyTestSuite : public testing::TestWithParam<std::tuple<MyType, std::string>> {
};

INSTANTIATE_TEST_SUITE_P(
    MyGroup, MyTestSuite,
    testing::Combine(
        testing::Values(MyType::MY_FOO, MyType::MY_BAR),
        testing::Values("A", "B")),
    [](const testing::TestParamInfo<MyTestSuite::ParamType>& info) {
      std::string name = absl::StrCat(
          std::get<0>(info.param) == MyType::MY_FOO ? "Foo" : "Bar",
          std::get<1>(info.param));
      absl::c_replace_if(name, [](char c) { return !std::isalnum(c); }, '_');
      return name;
    });

Typed Tests

Suppose you have multiple implementations of the same interface and want to make sure that all of them satisfy some common requirements. Or, you may have defined several types that are supposed to conform to the same “concept” and you want to verify it. In both cases, you want the same test logic repeated for different types.

假设同一个接口有多个实现,并且希望确保它们都满足某些公共需求。或者,你可能已经定义了几个应该符合相同“概念”的类型,并且你想要验证它。在这两种情况下,您都希望为不同的类型重复相同的测试逻辑。

While you can write one TEST or TEST_F for each type you want to test (and you may even factor the test logic into a function template that you invoke from the TEST), it’s tedious and doesn’t scale: if you want m tests over n types, you’ll end up writing m*n TESTs.

虽然你可以为想要测试的每种类型编写一个TESTTEST_F(你甚至可以将测试逻辑分解到从TEST中调用的函数模板中),但这很乏味且不可扩展:如果你想要在n类型上编写m个测试,你最终将编写m*nTEST

Typed tests allow you to repeat the same test logic over a list of types. You only need to write the test logic once, although you must know the type list when writing typed tests. Here’s how you do it:

类型化测试允许你在一组类型上重复相同的测试逻辑。虽然在编写类型化测试时必须知道类型列表,但您只需要编写一次测试逻辑。你可以这样做:

First, define a fixture class template. It should be parameterized by a type. Remember to derive it from ::testing::Test:

首先,定义一个fixture类模板。它应该被类型参数化。记住要从::testing::Test派生出来:

template <typename T>
class FooTest : public testing::Test {
 public:
  ...
  using List = std::list<T>;
  static T shared_;
  T value_;
};

Next, associate a list of types with the test suite, which will be repeated for each type in the list:

接下来,将一个类型列表和测试套件关联起来,对于列表中的每个类型都会重复这个操作:

using MyTypes = ::testing::Types<char, int, unsigned int>;
TYPED_TEST_SUITE(FooTest, MyTypes);

The type alias (using or typedef) is necessary for the TYPED_TEST_SUITE macro to parse correctly. Otherwise the compiler will think that each comma in the type list introduces a new macro argument.

类型别名(usingtypedef)是TYPED_TEST_SUITE宏正确解析所必需的。否则,编译器会认为类型列表中的每个逗号都引入了一个新的宏参数。

Then, use TYPED_TEST() instead of TEST_F() to define a typed test for this test suite. You can repeat this as many times as you want:

然后,使用 TYPED_TEST() 而不是TEST_F()来为这个测试套件定义一个类型化测试。你可以想重复多少次:

TYPED_TEST(FooTest, DoesBlah) {
  // Inside a test, refer to the special name TypeParam to get the type
  // parameter.  Since we are inside a derived class template, C++ requires
  // us to visit the members of FooTest via 'this'.
  //在测试中,通过特殊名称TypeParam来获取类型
  //参数。因为我们在一个派生类模板中,c++需要
  //我们通过` this `访问FooTest的成员。
  TypeParam n = this->value_;

  // To visit static members of the fixture, add the 'TestFixture::'
  // prefix.
  n += TestFixture::shared_;

  // To refer to typedefs in the fixture, add the 'typename TestFixture::'
  // prefix.  The 'typename' is required to satisfy the compiler.
  // 要在夹具中引用typedefs,添加` typename TestFixture:: `
  // 前缀。` typename `是编译器所必需的。
  typename TestFixture::List values;

  values.push_back(n);
  ...
}

TYPED_TEST(FooTest, HasPropertyA) { ... }

You can see [sample6_unittest.cc] for a complete example.

Type-Parameterized Tests / 类型参数化测试

Type-parameterized tests are like typed tests, except that they don’t require you to know the list of types ahead of time. Instead, you can define the test logic first and instantiate it with different type lists later. You can even instantiate it more than once in the same program.

类型参数化测试类似于类型测试,不同的是它们不需要你提前知道类型列表。相反,您可以首先定义测试逻辑,然后使用不同的类型列表将其实例化。你甚至可以在同一个程序中多次实例化它。

If you are designing an interface or concept, you can define a suite of type-parameterized tests to verify properties that any valid implementation of the interface/concept should have. Then, the author of each implementation can just instantiate the test suite with their type to verify that it conforms to the requirements, without having to write similar tests repeatedly. Here’s an example:

如果您正在设计一个接口或概念,您可以定义一套类型参数化测试来验证接口/概念的任何有效实现都应该具有的属性。然后,每个实现的作者可以用他们的类型实例化测试套件,以验证它符合需求,而不必重复编写类似的测试。下面是一个例子:

First, define a fixture class template, as we did with typed tests:

首先,和类型化测试一样,定义一个fixture类模板:

template <typename T>
class FooTest : public testing::Test {
  void DoSomethingInteresting();
  ...
};

Next, declare that you will define a type-parameterized test suite:

接下来,声明你将定义一个类型参数化的测试套件:

TYPED_TEST_SUITE_P(FooTest);

Then, use TYPED_TEST_P() to define a type-parameterized test. You can repeat this as many times as you want:

然后,使用TYPED_TEST_P()来定义一个类型参数化测试。你可以想重复多少次:

TYPED_TEST_P(FooTest, DoesBlah) {
  // Inside a test, refer to TypeParam to get the type parameter.
  TypeParam n = 0;

  // You will need to use `this` explicitly to refer to fixture members.
  this->DoSomethingInteresting()
  ...
}

TYPED_TEST_P(FooTest, HasPropertyA) { ... }

Now the tricky part: you need to register all test patterns using the REGISTER_TYPED_TEST_SUITE_P macro before you can instantiate them. The first argument of the macro is the test suite name; the rest are the names of the tests in this test suite:

现在棘手的部分:你需要使用REGISTER_TYPED_TEST_SUITE_P宏注册所有测试模式,然后才能实例化它们。宏的第一个参数是测试套件名称;其余是这个测试套件中的测试名称:

REGISTER_TYPED_TEST_SUITE_P(FooTest,
                            DoesBlah, HasPropertyA);

Finally, you are free to instantiate the pattern with the types you want. If you put the above code in a header file, you can #include it in multiple C++ source files and instantiate it multiple times.

最后,你可以自由地用你想要的类型实例化模式。如果你把上面的代码放在一个头文件中,你可以在多个c++源文件中#include它并多次实例化它。

using MyTypes = ::testing::Types<char, int, unsigned int>;
INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);

To distinguish different instances of the pattern, the first argument to the INSTANTIATE_TYPED_TEST_SUITE_P macro is a prefix that will be added to the actual test suite name. Remember to pick unique prefixes for different instances.

为了区分模式的不同实例,INSTANTIATE_TYPED_TEST_SUITE_P宏的第一个参数是一个前缀,它将被添加到实际的测试套件名称中。记住为不同的实例选择唯一的前缀。

In the special case where the type list contains only one type, you can write that type directly without ::testing::Types<...>, like this:

在类型列表只包含一种类型的特殊情况下,你可以直接编写这种类型,而不需要使用::testing::Types<...>,像这样:

INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, int);

You can see [sample6_unittest.cc] for a complete example.

Testing Private Code

If you change your software’s internal implementation, your tests should not break as long as the change is not observable by users. Therefore, per the black-box testing principle, most of the time you should test your code hrough its public interfaces.

如果你改变了你的软件的内部实现,你的测试应该不会中断,只要这种改变是用户无法观察到的。因此,根据黑盒测试原则,大多数情况下你应该通过公共接口来测试代码。

If you still find yourself needing to test internal implementation code, consider if there’s a better design. The desire to test internal implementation is often a sign that the class is doing too much. Consider extracting an implementation class, and testing it. Then use that implementation class in the original class.

**如果你发现自己仍然需要测试内部实现代码,请考虑是否有更好的设计。**希望测试内部实现通常是类做得太多的标志。考虑提取一个实现类,并对其进行测试。然后在原始类中使用该实现类。

If you absolutely have to test non-public interface code though, you can. There are two cases to consider:

如果你一定要测试非公共接口代码,你可以。有两种情况需要考虑。

  • Static functions ( not the same as static member functions!) or unnamed
    namespaces, and

    静态函数(与静态成员函数不同)或未命名的命名空间,以及

  • Private or protected class members

    私有的或受保护的类成员
    To test them, we use the following special techniques:
    为了测试它们,我们使用以下特殊技术。

  • Both static functions and definitions/declarations in an unnamed namespace
    are only visible within the same translation unit. To test them, you can
    #include the entire .cc file being tested in your *_test.cc file.
    (#including .cc files is not a good way to reuse code - you should not do this in production code!)

    未命名命名空间中的静态函数和定义/声明只在同一个转换单元中可见。要测试它们,你可以#include整个。在你的*_test. Cc文件中测试。cc的文件。(#包括”。Cc `文件不是重用代码的好方法——你不应该在生产代码中这样做!)

    However, a better approach is to move the private code into the
    foo::internal namespace, where foo is the namespace your project
    normally uses, and put the private declarations in a *-internal.h file.
    Your production .cc files and your tests are allowed to include this
    internal header, but your clients are not. This way, you can fully test your internal implementation without leaking it to your clients.

    然而,更好的方法是将私有代码移动到foo::internal命名空间中,其中foo是项目通常使用的命名空间,并将私有声明放在*-internal.h文件中。你的产品’。Cc `文件和你的测试允许包含这个内部头文件,但你的客户端不允许。这样,您可以完全测试您的内部实现,而不会将其泄漏给您的客户端。

  • Private class members are only accessible from within the class or by friends. To access a class’ private members, you can declare your test fixture as a friend to the class and define accessors in your fixture. Tests using the fixture can then access the private members of your production class via the accessors in the fixture. Note that even though your fixture is a friend to your production class, your tests are not automatically friends to it, as they are technically defined in sub-classes of the fixture.

    私有类成员只能在类内部或友元访问。要访问类的私有成员,可以将测试夹具声明为类的友元,并在夹具中定义访问器。然后,使用夹具的测试可以通过夹具中的访问器访问生产类的私有成员。注意,即使fixture是生产类的友元,测试也不会自动成为生产类的友元,因为测试在技术上是在fixture的子类中定义的。

    Another way to test private members is to refactor them into an implementation class, which is then declared in a *-internal.h file. Your clients aren’t allowed to include this header but your tests can. Such is called the Pimpl (Private Implementation) idiom.

    另一种测试私有成员的方法是将它们重构为一个实现类,然后在*-internal.h文件中声明这个实现类。您的客户端不允许包含此header,但您的测试可以。这就是所谓的Pimpl(Private Implementation)习语。

    Or, you can declare an individual test as a friend of your class by adding
    this line in the class body:

    或者,你可以声明一个单独的测试作为类的友元,在类的主体中添加下面这行代码:

        FRIEND_TEST(TestSuiteName, TestName);
    

    For example,

    // foo.h
    class Foo {
      ...
     private:
      FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
    
      int Bar(void* x);
    };
    
    // foo_test.cc
    ...
    TEST(FooTest, BarReturnsZeroOnNull) {
      Foo foo;
      EXPECT_EQ(foo.Bar(NULL), 0);  // Uses Foo's private member Bar().
    }
    

    Pay special attention when your class is defined in a namespace. If you want your test fixtures and tests to be friends of your class, then they must be defined in the exact same namespace (no anonymous or inline namespaces).

    在命名空间中定义类时要特别注意。如果希望测试固件和测试成为类的友元,那么它们必须定义在完全相同的命名空间中(没有匿名或内联命名空间)。

    For example, if the code to be tested looks like:

    namespace my_namespace {
    
    class Foo {
      friend class FooTest;
      FRIEND_TEST(FooTest, Bar);
      FRIEND_TEST(FooTest, Baz);
      ... definition of the class Foo ...
    };
    
    }  // namespace my_namespace
    

    Your test code should be something like:

    namespace my_namespace {
    
    class FooTest : public testing::Test {
     protected:
      ...
    };
    
    TEST_F(FooTest, Bar) { ... }
    TEST_F(FooTest, Baz) { ... }
    
    }  // namespace my_namespace
    

“Catching” Failures / “捕捉”失败

If you are building a testing utility on top of GoogleTest, you’ll want to test your utility. What framework would you use to test it? GoogleTest, of course.

如果你正在构建一个基于GoogleTest的测试工具,你会想要测试你的工具。你会用什么框架来测试它?当然是GoogleTest。

The challenge is to verify that your testing utility reports failures correctly. In frameworks that report a failure by throwing an exception, you could catch the exception and assert on it. But GoogleTest doesn’t use exceptions, so how do we test that a piece of code generates an expected failure?

挑战是验证你的测试工具正确地报告失败。在通过抛出异常来报告失败的框架中,你可以捕获异常并对其进行断言。但是GoogleTest不使用异常,那么我们如何测试一段代码是否产生了预期的失败呢?

"gtest/gtest-spi.h" contains some constructs to do this.
After #including this header, you can use

“gtest/gtest-spi.h”包含了一些实现这一功能的结构。在#包含此header之后,您可以使用

  EXPECT_FATAL_FAILURE(statement, substring);

to assert that statement generates a fatal (e.g. ASSERT_*) failure in the
current thread whose message contains the given substring, or use

断言statement生成一个fatal(例如:ASSERT_*)失败当前线程的消息包含给定的substring,或使用

  EXPECT_NONFATAL_FAILURE(statement, substring);

if you are expecting a non-fatal (e.g. EXPECT_*) failure.

如果你期待一个非致命的(例如:“EXPECT_ *”)失败。

Only failures in the current thread are checked to determine the result of this type of expectations. If statement creates new threads, failures in these threads are also ignored. If you want to catch failures in other threads as well, use one of the following macros instead:

只有当前线程中的失败才会被检查,以确定这种类型的期望的结果。如果statement创建了新的线程,这些线程中的失败也会被忽略。 如果你也想在其他线程中捕获错误,可以使用以下宏:

  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substring);
  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substring);

{: .callout .note}
NOTE: Assertions from multiple threads are currently not supported on Windows.

Windows目前不支持多线程中的断言。

For technical reasons, there are some caveats:

出于技术原因,有以下几点需要注意。

  1. You cannot stream a failure message to either macro.

    您不能向这两个宏发送失败消息。

  2. statement in EXPECT_FATAL_FAILURE{_ON_ALL_THREADS}() cannot reference
    local non-static variables or non-static members of this object.

    EXPECT_FATAL_FAILURE{_ON_ALL_THREADS}()中的statement无法引用局部非静态变量或this对象的非静态成员。

  3. statement in EXPECT_FATAL_FAILURE{_ON_ALL_THREADS}() cannot return a
    value.

    EXPECT_FATAL_FAILURE{_ON_ALL_THREADS}()中的statement不能返回值。

Registering tests programmatically / 以编程方式注册测试

The TEST macros handle the vast majority of all use cases, but there are few
where runtime registration logic is required. For those cases, the framework
provides the ::testing::RegisterTest that allows callers to register arbitrary
tests dynamically.

TEST宏处理了绝大多数用例,但很少需要运行时注册逻辑。对于这些情况,框架提供了::testing::RegisterTest,允许调用者动态注册任意测试。

This is an advanced API only to be used when the TEST macros are insufficient.
The macros should be preferred when possible, as they avoid most of the
complexity of calling this function.

这是一个高级API,仅在TEST宏不足时使用。在可能的情况下,应该优先使用宏,因为它们避免了调用该函数的大部分复杂性。

It provides the following signature:

它提供了以下签名:

template <typename Factory>
TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
                       const char* type_param, const char* value_param,
                       const char* file, int line, Factory factory);

The factory argument is a factory callable (move-constructible) object or
function pointer that creates a new instance of the Test object. It handles
ownership to the caller. The signature of the callable is Fixture*(), where
Fixture is the test fixture class for the test. All tests registered with the
same test_suite_name must return the same fixture type. This is checked at
runtime.

factory参数是一个工厂可调用(可移动构造)对象或函数指针,用于创建测试对象的新实例。它处理调用者的所有权。可调用对象的签名是Fixture*(),其中Fixture是用于测试的测试夹具类。所有使用相同的test_suite_name注册的测试必须返回相同的fixture类型。这在运行时检查。

The framework will infer the fixture class from the factory and will call the
SetUpTestSuite and TearDownTestSuite for it.

框架将从工厂中推断出fixture类,并为其调用setuptestsuiteTearDownTestSuite

Must be called before RUN_ALL_TESTS() is invoked, otherwise behavior is
undefined.

必须在调用RUN_ALL_TESTS()之前调用,否则行为未定义。

Use case example: 用例

class MyFixture : public testing::Test {
 public:
  // All of these optional, just like in regular macro usage.
  static void SetUpTestSuite() { ... }
  static void TearDownTestSuite() { ... }
  void SetUp() override { ... }
  void TearDown() override { ... }
};

class MyTest : public MyFixture {
 public:
  explicit MyTest(int data) : data_(data) {}
  void TestBody() override { ... }

 private:
  int data_;
};

void RegisterMyTests(const std::vector<int>& values) {
  for (int v : values) {
    testing::RegisterTest(
        "MyFixture", ("Test" + std::to_string(v)).c_str(), nullptr,
        std::to_string(v).c_str(),
        __FILE__, __LINE__,
        // Important to use the fixture type as the return type here.
        [=]() -> MyFixture* { return new MyTest(v); });
  }
}
...
int main(int argc, char** argv) {
  testing::InitGoogleTest(&argc, argv);
  std::vector<int> values_to_test = LoadValuesFromConfig();
  RegisterMyTests(values_to_test);
  ...
  return RUN_ALL_TESTS();
}

Getting the Current Test’s Name

Sometimes a function may need to know the name of the currently running test. For example, you may be using the SetUp() method of your test fixture to set the golden file name based on which test is running. The TestInfo class has this information.

有时,函数可能需要知道当前运行的测试的名称。例如,您可以使用测试夹具的SetUp()方法来设置基于正在运行的测试的黄金文件名。[’ TestInfo '](reference/testing. md#testinfo)类有这个信息。

To obtain a TestInfo object for the currently running test, call current_test_info() on the UnitTest singleton object:

要获取当前运行的测试的TestInfo对象,在[UnitTest](reference/testing. md#unittest)单例对象上调用current_test_info():

  // Gets information about the currently running test.
  // Do NOT delete the returned object - it's managed by the UnitTest class.
  const testing::TestInfo* const test_info =
      testing::UnitTest::GetInstance()->current_test_info();

  printf("We are in test %s of test suite %s.\n",
         test_info->name(),
         test_info->test_suite_name());

current_test_info() returns a null pointer if no test is running. In particular, you cannot find the test suite name in SetUpTestSuite(), TearDownTestSuite() (where you know the test suite name implicitly), or functions called from them.

如果没有测试正在运行,current_test_info()返回null指针。特别是,你无法在SetUpTestSuite()TearDownTestSuite()(在这里你隐式地知道测试套件名称)中找到测试套件名称,或者从它们中调用的函数。

Extending GoogleTest by Handling Test Events / 通过处理测试事件扩展GoogleTest

GoogleTest provides an event listener API to let you receive notifications about the progress of a test program and test failures. The events you can listen to include the start and end of the test program, a test suite, or a test method, among others. You may use this API to augment or replace the standard console output, replace the XML output, or provide a completely different form of output, such as a GUI or a database. You can also use test events as checkpoints to implement a resource leak checker, for example.

GoogleTest提供了一个事件监听API来让你接收关于测试程序进展和测试失败的通知。您可以监听的事件包括测试程序的开始和结束、测试套件或测试方法,等等。您可以使用此API来扩充或替换标准控制台输出、替换XML输出或提供完全不同的输出形式,例如GUI或数据库。例如,您还可以使用测试事件作为检查点来实现资源泄漏检查器。

Defining Event Listeners / 定义事件监听器

To define a event listener, you subclass either testing::TestEventListener or testing::EmptyTestEventListener The former is an (abstract) interface, where each pure virtual method can be overridden to handle a test event (For example, when a test starts, the OnTestStart() method will be called.). The latter provides an empty implementation of all methods in the interface, such that a subclass only needs to override the methods it cares about.

要定义一个事件监听器,你可以继承testing::TestEventListenertesting::EmptyTestEventListener前者是一个(抽象)接口,其中每个纯虚拟方法都可以被覆盖以处理测试事件(例如,当测试开始时,OnTestStart()方法将被调用。)后者提供了接口中所有方法的空实现,这样子类只需要覆盖它关心的方法。

When an event is fired, its context is passed to the handler function as an argument. The following argument types are used:

当事件被触发时,它的上下文会作为参数传递给处理程序函数。使用的参数类型如下:

  • UnitTest reflects the state of the entire test program,

    UnitTest反映了整个测试程序的状态,

  • TestSuite has information about a test suite, which can contain one or more
    tests,

    TestSuite包含关于测试套件的信息,可以包含一个或多个测试中,

  • TestInfo contains the state of a test, and

    TestInfo包含测试的状态和

  • TestPartResult represents the result of a test assertion.

    TestPartResult表示测试断言的结果。

An event handler function can examine the argument it receives to find out interesting information about the event and the test program’s state.

事件处理程序函数可以检查它接收到的参数,以找到有关事件和测试程序状态的有趣信息。

Here’s an example:

  class MinimalistPrinter : public testing::EmptyTestEventListener {
    // Called before a test starts.
    void OnTestStart(const testing::TestInfo& test_info) override {
      printf("*** Test %s.%s starting.\n",
             test_info.test_suite_name(), test_info.name());
    }

    // Called after a failed assertion or a SUCCESS().
    void OnTestPartResult(const testing::TestPartResult& test_part_result) override {
      printf("%s in %s:%d\n%s\n",
             test_part_result.failed() ? "*** Failure" : "Success",
             test_part_result.file_name(),
             test_part_result.line_number(),
             test_part_result.summary());
    }

    // Called after a test ends.
    void OnTestEnd(const testing::TestInfo& test_info) override {
      printf("*** Test %s.%s ending.\n",
             test_info.test_suite_name(), test_info.name());
    }
  };

Using Event Listeners

To use the event listener you have defined, add an instance of it to the GoogleTest event listener list (represented by class TestEventListeners - note the “s” at the end of the name) in your main() function, before calling RUN_ALL_TESTS():

要使用你定义的事件监听器,在调用RUN_ALL_TESTS()之前,将它的一个实例添加到main()函数中的GoogleTest事件监听器列表(由类TestEventListeners表示——注意名称末尾的“s”):

int main(int argc, char** argv) {
  testing::InitGoogleTest(&argc, argv);
  // Gets hold of the event listener list.
  testing::TestEventListeners& listeners =
      testing::UnitTest::GetInstance()->listeners();
  // Adds a listener to the end.  GoogleTest takes the ownership.
  listeners.Append(new MinimalistPrinter);
  return RUN_ALL_TESTS();
}

There’s only one problem: the default test result printer is still in effect, so its output will mingle with the output from your minimalist printer. To suppress the default printer, just release it from the event listener list and delete it. You can do so by adding one line:

只有一个问题:默认的测试结果打印机仍然有效,因此它的输出将与您的极简打印机的输出混合。要抑制默认打印机,只需从事件监听器列表中释放它并删除它。你可以通过添加一行代码来实现:

  ...
  delete listeners.Release(listeners.default_result_printer());
  listeners.Append(new MinimalistPrinter);
  return RUN_ALL_TESTS();

Now, sit back and enjoy a completely different output from your tests. For more
details, see [sample9_unittest.cc].

现在,坐下来享受测试完全不同的输出吧。更多细节请参见sample9_unittest.cc 中的 “Event listener example”。

You may append more than one listener to the list. When an On*Start() or
OnTestPartResult() event is fired, the listeners will receive it in the order
they appear in the list (since new listeners are added to the end of the list,
the default text printer and the default XML generator will receive the event
first). An On*End() event will be received by the listeners in the reverse
order. This allows output by listeners added later to be framed by output from
listeners added earlier.

你可以在列表中添加多个监听器。当 On*Start()OnTestPartResult() 定义事件监听器 事件被触发时,监听器将按照它们在列表中出现的顺序接收事件(因为新的监听器被添加到列表的末尾,默认的文本打印机和默认的XML生成器将首先接收事件)。On*End()事件将以相反的顺序被监听器接收。这使得后面添加的监听器的输出可以被前面添加的监听器的输出框起来。

Generating Failures in Listeners / 在监听器中生成故障

You may use failure-raising macros (EXPECT_*(), ASSERT_*(), FAIL(), etc)
when processing an event. There are some restrictions:

在处理事件时,你可以使用引发失败的宏(EXPECT_*()ASSERT_*()FAIL()等)。这里有一些限制。

  1. You cannot generate any failure in OnTestPartResult() (otherwise it will
    cause OnTestPartResult() to be called recursively).

    你不能在OnTestPartResult()中产生任何失败(否则它将导致OnTestPartResult()被递归调用)。

  2. A listener that handles OnTestPartResult() is not allowed to generate any
    failure.

    处理OnTestPartResult()的监听器不允许产生任何失败。

When you add listeners to the listener list, you should put listeners that
handle OnTestPartResult() before listeners that can generate failures. This
ensures that failures generated by the latter are attributed to the right test
by the former.

当你将监听器添加到监听器列表时,你应该将处理OnTestPartResult()的监听器放在可能产生错误的监听器之前。这确保了后者产生的故障归因于前者的正确测试。

See [sample10_unittest.cc] for an example of a failure-raising listener.

sample10_unittest.cc "Failure-raising listener example"

Running Test Programs: Advanced Options / 运行测试程序:高级选项

GoogleTest test programs are ordinary executables. Once built, you can run them
directly and affect their behavior via the following environment variables
and/or command line flags. For the flags to work, your programs must call
::testing::InitGoogleTest() before calling RUN_ALL_TESTS().

GoogleTest测试程序是普通的可执行文件。一旦构建完成,你可以直接运行它们,并通过以下环境变量和/或命令行标志影响它们的行为。为了让标志起作用,你的程序必须在调用RUN_ALL_TESTS()之前调用::testing::InitGoogleTest()

To see a list of supported flags and their usage, please run your test program
with the --help flag. You can also use -h, -?, or /? for short.

要查看支持的标志及其用法列表,请使用——help标志运行您的测试程序。你也可以使用-h-?,或者`/?简而言之。

If an option is specified both by an environment variable and by a flag, the
latter takes precedence.

如果一个选项同时由环境变量和标志指定,则后者优先。

Selecting Tests

Listing Test Names

Sometimes it is necessary to list the available tests in a program before
running them so that a filter may be applied if needed. Including the flag
--gtest_list_tests overrides all other flags and lists tests in the following
format:

有时,在运行测试之前,必须列出程序中可用的测试,以便在需要时应用过滤器。包括 --gtest_list_tests 标志将覆盖所有其他标志,并以以下格式列出测试:

TestSuite1.
  TestName1
  TestName2
TestSuite2.
  TestName

None of the tests listed are actually run if the flag is provided. There is no
corresponding environment variable for this flag.

如果提供了这个标志,列出的所有测试实际上都不会运行。该标志没有对应的环境变量。

Running a Subset of the Tests / 运行测试的子集

By default, a GoogleTest program runs all tests the user has defined. Sometimes,
you want to run only a subset of the tests (e.g. for debugging or quickly
verifying a change). If you set the GTEST_FILTER environment variable or the
--gtest_filter flag to a filter string, GoogleTest will only run the tests
whose full names (in the form of TestSuiteName.TestName) match the filter.

默认情况下,GoogleTest程序会运行用户定义的所有测试。有时,你只想运行一部分测试(例如调试或快速验证变更)。如果你将 **GTEST_FILTER环境变量或——GTEST_FILTER**标志设置为一个过滤器字符串,GoogleTest将只运行那些全名(以TestSuiteName.TestName的形式)与过滤器匹配的测试。

The format of a filter is a ‘:’-separated list of wildcard patterns (called
the positive patterns) optionally followed by a ‘-’ and another
:’-separated pattern list (called the negative patterns). A test matches
the filter if and only if it matches any of the positive patterns but does not
match any of the negative patterns.

过滤器的格式是一个由::"分隔的通配符模式列表(称为正模式),后面可以有一个-- "和另一个::"分隔的模式列表(称为负模式)。当且仅当测试匹配任何正模式,而不匹配任何负模式时,测试与过滤器匹配。

A pattern may contain '*' (matches any string) or '?' (matches any single
character). For convenience, the filter '*-NegativePatterns' can be also
written as '-NegativePatterns'.

一个模式可以包含'*'(匹配任何字符串)或者 '?'(匹配任意单个字符)。为了方便起见,过滤器'*-NegativePatterns'也可以写成'-NegativePatterns'

For example:

  • ./foo_test Has no flag, and thus runs all its tests.

    ./foo_test没有标志,因此运行它的所有测试。

  • ./foo_test --gtest_filter=* Also runs everything, due to the single
    match-everything * value.

    ./foo_test --gtest_filter=也运行所有内容,因为有一个匹配所有值。

  • ./foo_test --gtest_filter=* Runs everything in test suite
    FooTest .

    /foo_test --gtest_filter =FooTest。*运行测试套件中的所有内容FooTest

  • ./foo_test --gtest_filter=*Null*:*Constructor* Runs any test whose full
    name contains either "Null" or "Constructor" .

    ./foo_test --gtest_filter=*Null*:*Constructor*运行所有全名包含"Null""Constructor"的测试。

  • ./foo_test --gtest_filter=-*DeathTest.* Runs all non-death tests.

    ./foo_test --gtest_filter=-*DeathTest.*运行所有非死亡测试。

  • ./foo_test --gtest_filter=FooTest.*-FooTest.Bar Runs everything in test
    suite FooTest except FooTest.Bar.

    /foo_test --gtest_filter=FooTest.*-FooTest.Bar 运行测试套件FooTest中的所有内容,除了FooTest.Bar。

  • ./foo_test --gtest_filter=FooTest.*:BarTest.*-FooTest.Bar:BarTest.Foo Runs
    everything in test suite FooTest except FooTest.Bar and everything in
    test suite BarTest except BarTest.Foo.

    ./foo_test --gtest_filter=FooTest.*:BarTest.*-FooTest.Bar:BarTest.Foo运行测试套件FooTest中除FooTest之外的所有内容。Bar和测试套件BarTest中除了BarTest. foo之外的所有东西。

Stop test execution upon first failure / 第一次失败时停止测试执行

By default, a GoogleTest program runs all tests the user has defined. In some
cases (e.g. iterative test development & execution) it may be desirable stop
test execution upon first failure (trading improved latency for completeness).
If GTEST_FAIL_FAST environment variable or --gtest_fail_fast flag is set,
the test runner will stop execution as soon as the first test failure is found.

默认情况下,GoogleTest程序会运行用户定义的所有测试。在某些情况下(例如迭代测试开发和执行),可能需要在第一次失败时停止测试执行(以改进的延迟换取完整性)。如果设置了GTEST_FAIL_FAST环境变量或 --gtest_fail_fast 标志,测试运行器将在第一个测试失败时立即停止执行。

Temporarily Disabling Tests

If you have a broken test that you cannot fix right away, you can add the
DISABLED_ prefix to its name. This will exclude it from execution. This is
better than commenting out the code or using #if 0, as disabled tests are
still compiled (and thus won’t rot).

如果你有一个失败的测试无法立即修复,你可以在它的名称前添加DISABLED_前缀。这会将它排除在执行之外。这比注释掉代码或者像禁用测试那样使用#if 0要好仍然是编译过的(因此不会腐烂)。

If you need to disable all tests in a test suite, you can either add DISABLED_
to the front of the name of each test, or alternatively add it to the front of
the test suite name.

如果你需要禁用一个测试套件中的所有测试,你可以在每个测试名称的前面添加 DISABLED_ ,或者将它添加到测试套件名称的前面。

For example, the following tests won’t be run by GoogleTest, even though they
will still be compiled:

例如,下面的测试不会被GoogleTest运行,即使它们仍然会被编译:

// Tests that Foo does Abc.
TEST(FooTest, DISABLED_DoesAbc) { ... }

class DISABLED_BarTest : public testing::Test { ... };

// Tests that Bar does Xyz.
TEST_F(DISABLED_BarTest, DoesXyz) { ... }

{: .callout .note}
NOTE: This feature should only be used for temporary pain-relief. You still have
to fix the disabled tests at a later date. As a reminder, GoogleTest will print
a banner warning you if a test program contains any disabled tests.

注意:此功能只能用于暂时缓解疼痛。您仍然需要在稍后的日期修复禁用的测试。作为提醒,如果测试程序包含任何被禁用的测试,GoogleTest将打印一条横幅警告你。

{: .callout .tip}
TIP: You can easily count the number of disabled tests you have using
grep. This number can be used as a metric for
improving your test quality.

提示:你可以使用grep轻松地计算禁用测试的数量。这个数字可以作为提高测试质量的指标。

Temporarily Enabling Disabled Tests

To include disabled tests in test execution, just invoke the test program with
the --gtest_also_run_disabled_tests flag or set the
GTEST_ALSO_RUN_DISABLED_TESTS environment variable to a value other than 0.
You can combine this with the --gtest_filter flag to further select which
disabled tests to run.

要在测试执行中包含禁用的测试,只需使用 --gtest_also_run_disabled_tests 标志调用测试程序,或者将gtest_also_run_disabled_tests环境变量设置为0以外的值。您可以将此与——gtest_filter标志结合使用,以进一步选择要运行哪些禁用的测试。

Repeating the Tests

Once in a while you’ll run into a test whose result is hit-or-miss. Perhaps it
will fail only 1% of the time, making it rather hard to reproduce the bug under
a debugger. This can be a major source of frustration.

偶尔你会遇到一个测试,其结果是杂乱无章的。也许只有1%的情况会失败,这使得在调试器下很难重现这个bug。这可能是沮丧的主要来源。

The --gtest_repeat flag allows you to repeat all (or selected) test methods in
a program many times. Hopefully, a flaky test will eventually fail and give you
a chance to debug. Here’s how to use it:

——gtest_repeat标志允许你多次重复程序中所有(或选定)的测试方法。希望一个不靠谱的测试最终会失败,给你一个调试的机会。使用方法如下:

$ foo_test --gtest_repeat=1000
Repeat foo_test 1000 times and don't stop at failures.

$ foo_test --gtest_repeat=-1
A negative count means repeating forever.

$ foo_test --gtest_repeat=1000 --gtest_break_on_failure
Repeat foo_test 1000 times, stopping at the first failure.  This
is especially useful when running under a debugger: when the test
fails, it will drop into the debugger and you can then inspect
variables and stacks.

$ foo_test --gtest_repeat=1000 --gtest_filter=FooBar.*
Repeat the tests whose name matches the filter 1000 times.

If your test program contains
global set-up/tear-down code, it will be
repeated in each iteration as well, as the flakiness may be in it. To avoid
repeating global set-up/tear-down, specify
--gtest_recreate_environments_when_repeating=false{.nowrap}.

如果你的测试程序包含global set-up/tear-down代码,它也将在每次迭代中重复,因为不稳定可能在其中。要避免重复全局设置/删除,请指定——gtest_recreate_environments_when_repeating=false{.nowrap}。

You can also specify the repeat count by setting the GTEST_REPEAT environment
variable.

你也可以通过设置GTEST_REPEAT环境变量来指定重复次数。

Shuffling the Tests / 修改测试

You can specify the --gtest_shuffle flag (or set the GTEST_SHUFFLE
environment variable to 1) to run the tests in a program in a random order.
This helps to reveal bad dependencies between tests.

你可以指定——gtest_shuffle标志(或者将gtest_shuffle环境变量设置为1)以随机顺序在程序中运行测试。这有助于揭示测试之间的不良依赖关系。

By default, GoogleTest uses a random seed calculated from the current time.
Therefore you’ll get a different order every time. The console output includes
the random seed value, such that you can reproduce an order-related test failure
later. To specify the random seed explicitly, use the --gtest_random_seed=SEED
flag (or set the GTEST_RANDOM_SEED environment variable), where SEED is an
integer in the range [0, 99999]. The seed value 0 is special: it tells
GoogleTest to do the default behavior of calculating the seed from the current
time.

默认情况下,GoogleTest使用当前时间计算的随机种子。因此,每次你都会得到不同的顺序。控制台输出包括随机种子值,这样您就可以在稍后重现一个与订单相关的测试失败。要显式指定随机种子,可以使用——gtest_random_seed= seed标志(或者设置gtest_random_seed环境变量),其中seed是[0,99999]范围内的整数。种子值0是特殊的:它告诉GoogleTest按照默认行为从当前时间计算种子。

If you combine this with --gtest_repeat=N, GoogleTest will pick a different
random seed and re-shuffle the tests in each iteration.

如果你将它与--gtest_repeat=N结合起来,GoogleTest将在每次迭代中选择不同的随机种子并重新打乱测试。

Distributing Test Functions to Multiple Machines / 将测试函数分布到多台机器上

If you have more than one machine you can use to run a test program, you might
want to run the test functions in parallel and get the result faster. We call
this technique sharding, where each machine is called a shard.

如果你有多台机器可以用来运行测试程序,你可能希望并行运行测试函数,更快地得到结果。我们称这种技术为 sharding ,每台机器都称为 shard

GoogleTest is compatible with test sharding. To take advantage of this feature,
your test runner (not part of GoogleTest) needs to do the following:

GoogleTest兼容测试分片。为了利用这个功能,你的测试运行程序(不是GoogleTest的一部分)需要做以下事情:

  1. Allocate a number of machines (shards) to run the tests.

    分配一些机器(分片)来运行测试。

  2. On each shard, set the GTEST_TOTAL_SHARDS environment variable to the total
    number of shards. It must be the same for all shards.

    在每个分片上,将GTEST_TOTAL_SHARDS环境变量设置为总和分片数。所有分片都必须相同。

  3. On each shard, set the GTEST_SHARD_INDEX environment variable to the index
    of the shard. Different shards must be assigned different indices, which
    must be in the range [0, GTEST_TOTAL_SHARDS - 1].

    在每个分片上,将GTEST_SHARD_INDEX环境变量设置为索引碎片的。不同的分片必须分配不同的索引必须在[0,GTEST_TOTAL_SHARDS - 1]的范围内。

  4. Run the same test program on all shards. When GoogleTest sees the above two
    environment variables, it will select a subset of the test functions to run.
    Across all shards, each test function in the program will be run exactly
    once.

    在所有分片上运行相同的测试程序。当GoogleTest看到上面两个环境变量,它将选择一个测试函数的子集来运行。在所有分片中,程序中的每个测试函数都将准确地运行一次。

  5. Wait for all shards to finish, then collect and report the results.

    等待所有分片完成,然后收集并报告结果。

Your project may have tests that were written without GoogleTest and thus don’t understand this protocol. In order for your test runner to figure out which test supports sharding, it can set the environment variable GTEST_SHARD_STATUS_FILE to a non-existent file path. If a test program supports sharding, it will create this file to acknowledge that fact; otherwise it will not create it. The actual contents of the file are not important at this time, although we may put some useful information in it in the future.

你的项目可能有一些测试是在没有GoogleTest的情况下编写的,因此无法理解这个协议。为了让你的测试运行器知道哪个测试支持分片,它可以将环境变量GTEST_SHARD_STATUS_FILE设置为一个不存在的文件路径。如果测试程序支持分片,它会创建这个文件来确认这一事实;否则它将不会创建它。该文件的实际内容目前并不重要,尽管将来我们可能会在其中添加一些有用的信息。

Here’s an example to make it clear. Suppose you have a test program foo_test that contains the following 5 test functions:

这里有一个例子来说明。假设你有一个测试程序foo_test,它包含以下5个测试函数:

TEST(A, V)
TEST(A, W)
TEST(B, X)
TEST(B, Y)
TEST(B, Z)

Suppose you have 3 machines at your disposal. To run the test functions in
parallel, you would set GTEST_TOTAL_SHARDS to 3 on all machines, and set
GTEST_SHARD_INDEX to 0, 1, and 2 on the machines respectively. Then you would
run the same foo_test on each machine.

假设有3台机器可供使用。要并行运行测试函数,你需要在所有机器上将GTEST_TOTAL_SHARDS设置为3,并在所有机器上分别将GTEST_SHARD_INDEX设置为0、1和2。然后在每台机器上运行相同的foo_test

GoogleTest reserves the right to change how the work is distributed across the
shards, but here’s one possible scenario:

GoogleTest保留改变工作在各个分片上的分配方式的权利,但这里有一种可能的情况:

  • Machine #0 runs A.V and B.X.
  • Machine #1 runs A.W and B.Y.
  • Machine #2 runs B.Z.

Controlling Test Output / 控制测试输出

Colored Terminal Output / 彩色终端输出

GoogleTest can use colors in its terminal output to make it easier to spot the
important information:

GoogleTest可以在终端输出中使用颜色,以便更容易识别重要信息:

...
[----------] 1 test from FooTest
[ RUN      ] FooTest.DoesAbc
[       OK ] FooTest.DoesAbc
[----------] 2 tests from BarTest
[ RUN      ] BarTest.HasXyzProperty
[       OK ] BarTest.HasXyzProperty
[ RUN      ] BarTest.ReturnsTrueOnSuccess
... some error messages ...
[   FAILED ] BarTest.ReturnsTrueOnSuccess
...
[==========] 30 tests from 14 test suites ran.
[   PASSED ] 28 tests.
[   FAILED ] 2 tests, listed below:
[   FAILED ] BarTest.ReturnsTrueOnSuccess
[   FAILED ] AnotherTest.DoesXyz

 2 FAILED TESTS

You can set the GTEST_COLOR environment variable or the --gtest_color
command line flag to yes, no, or auto (the default) to enable colors,
disable colors, or let GoogleTest decide. When the value is auto, GoogleTest
will use colors if and only if the output goes to a terminal and (on non-Windows
platforms) the TERM environment variable is set to xterm or xterm-color.

你可以设置环境变量GTEST_COLOR或命令行参数——GTEST_COLORyesnoauto(默认值)来启用颜色,禁用颜色,或者让GoogleTest来决定。当值为 auto 时,当且仅当输出到终端并且(在非windows平台上)环境变量 TERM 设置为 xtermxterm-color时,GoogleTest才会使用颜色。

Suppressing test passes / 抑制测试通过

By default, GoogleTest prints 1 line of output for each test, indicating if it
passed or failed. To show only test failures, run the test program with
--gtest_brief=1, or set the GTEST_BRIEF environment variable to 1.

默认情况下,GoogleTest为每个测试打印一行输出,表示测试通过还是失败。要只显示测试失败,请使用——gtest_brief=1运行测试程序,或者将gtest_brief环境变量设置为1

Suppressing the Elapsed Time / 抑制经过的时间

By default, GoogleTest prints the time it takes to run each test. To disable
that, run the test program with the --gtest_print_time=0 command line flag, or
set the GTEST_PRINT_TIME environment variable to 0.

默认情况下,GoogleTest打印运行每个测试所花费的时间。要禁用它,请使用——gtest_print_time=0命令行标志运行测试程序,或者将gtest_print_time环境变量设置为0

Suppressing UTF-8 Text Output / 抑制UTF-8文本输出

In case of assertion failures, GoogleTest prints expected and actual values of
type string both as hex-encoded strings as well as in readable UTF-8 text if
they contain valid non-ASCII UTF-8 characters. If you want to suppress the UTF-8
text because, for example, you don’t have an UTF-8 compatible output medium, run
the test program with --gtest_print_utf8=0 or set the GTEST_PRINT_UTF8
environment variable to 0.

在断言失败的情况下,GoogleTest会以十六进制编码的字符串和可读的UTF-8文本(如果它们包含有效的非ascii UTF-8字符)的形式打印出string类型的预期值和实际值。如果你想屏蔽UTF-8文本,例如,你没有UTF-8兼容的输出介质,可以用——gtest_print_utf8=0运行测试程序,或者将gtest_print_utf8环境变量设置为0

Generating an XML Report / 生成XML报告

GoogleTest can emit a detailed XML report to a file in addition to its normal
textual output. The report contains the duration of each test, and thus can help
you identify slow tests.

除了正常的文本输出外,GoogleTest还可以将详细的XML报告发送到文件中。该报告包含每个测试的持续时间,因此可以提供帮助您可以识别慢速测试。

To generate the XML report, set the GTEST_OUTPUT environment variable or the
--gtest_output flag to the string "xml:path_to_output_file", which will
create the file at the given location. You can also just use the string "xml",
in which case the output can be found in the test_detail.xml file in the
current directory.

要生成XML报告,将GTEST_OUTPUT环境变量或gtest_output设置为字符串" xml:path_to_output_file"在指定位置创建文件。你也可以只使用字符串"xml",在这种情况下,输出可以在test_detail.xml文件中找到当前目录。

If you specify a directory (for example, "xml:output/directory/" on Linux or
"xml:output\directory\" on Windows), GoogleTest will create the XML file in
that directory, named after the test executable (e.g. foo_test.xml for test
program foo_test or foo_test.exe). If the file already exists (perhaps left
over from a previous run), GoogleTest will pick a different name (e.g.
foo_test_1.xml) to avoid overwriting it.

如果你指定一个目录(例如,在Linux上是"xml:output/directory/",在Windows上是"xml:output\directory\"), GoogleTest将在该目录下创建一个xml文件,以测试可执行文件(例如:foo_test.xml用于测试程序foo_testfoo_test.exe)。如果文件已经存在(可能是上次运行留下的),GoogleTest将选择一个不同的名称(例如:foo_test_1.xml),以避免覆盖它。

The report is based on the junitreport Ant task. Since that format was
originally intended for Java, a little interpretation is required to make it
apply to GoogleTest tests, as shown here:

该报告基于Ant任务junitreport。因为这种格式原本是为Java设计的,所以需要稍微解释一下,才能用于GoogleTest的测试,如下所示:

<testsuites name="AllTests" ...>
  <testsuite name="test_case_name" ...>
    <testcase    name="test_name" ...>
      <failure message="..."/>
      <failure message="..."/>
      <failure message="..."/>
    </testcase>
  </testsuite>
</testsuites>
  • The root <testsuites> element corresponds to the entire test program.
  • <testsuite> elements correspond to GoogleTest test suites.
  • <testcase> elements correspond to GoogleTest test functions.

For instance, the following program: 以下面的程序为例

TEST(MathTest, Addition) { ... }
TEST(MathTest, Subtraction) { ... }
TEST(LogicTest, NonContradiction) { ... }

could generate this report:

<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="3" failures="1" errors="0" time="0.035" timestamp="2011-10-31T18:52:42" name="AllTests">
  <testsuite name="MathTest" tests="2" failures="1" errors="0" time="0.015">
    <testcase name="Addition" file="test.cpp" line="1" status="run" time="0.007" classname="">
      <failure message="Value of: add(1, 1)&#x0A;  Actual: 3&#x0A;Expected: 2" type="">...</failure>
      <failure message="Value of: add(1, -1)&#x0A;  Actual: 1&#x0A;Expected: 0" type="">...</failure>
    </testcase>
    <testcase name="Subtraction" file="test.cpp" line="2" status="run" time="0.005" classname="">
    </testcase>
  </testsuite>
  <testsuite name="LogicTest" tests="1" failures="0" errors="0" time="0.005">
    <testcase name="NonContradiction" file="test.cpp" line="3" status="run" time="0.005" classname="">
    </testcase>
  </testsuite>
</testsuites>

Things to note: 注意事项:

  • The tests attribute of a <testsuites> or <testsuite> element tells how
    many test functions the GoogleTest program or test suite contains, while the
    failures attribute tells how many of them failed.

    <testsuite><testsuite>元素的tests属性告诉我们GoogleTest程序或测试套件包含多少个测试函数,而failures属性告诉我们有多少个函数失败了。

  • The time attribute expresses the duration of the test, test suite, or
    entire test program in seconds.

    time属性以秒为单位表示测试、测试套件或整个测试程序的持续时间。

  • The timestamp attribute records the local date and time of the test
    execution.

    timestamp属性记录了测试执行的本地日期和时间。

  • The file and line attributes record the source file location, where the
    test was defined.

    fileline属性记录了定义测试的源文件位置。

  • Each <failure> element corresponds to a single failed GoogleTest
    assertion.

    每个<failure>元素对应一个失败的GoogleTest断言。

Generating a JSON Report / 生成JSON报告

GoogleTest can also emit a JSON report as an alternative format to XML. To
generate the JSON report, set the GTEST_OUTPUT environment variable or the
--gtest_output flag to the string "json:path_to_output_file", which will
create the file at the given location. You can also just use the string
"json", in which case the output can be found in the test_detail.json file
in the current directory.

GoogleTest还可以生成JSON报告,作为XML的替代格式。要生成JSON格式的报告,可以设置GTEST_OUTPUT环境变量,或者将——GTEST_OUTPUT设置为字符串" JSON:path_to_output_file",这将在给定位置创建文件。你也可以只使用字符串"json",在这种情况下,输出可以在test_detail.json中找到。.Json文件在当前目录。

The report format conforms to the following JSON Schema:

报表格式符合以下JSON格式:

{
  "$schema": "http://json-schema.org/schema#",
  "type": "object",
  "definitions": {
    "TestCase": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "tests": { "type": "integer" },
        "failures": { "type": "integer" },
        "disabled": { "type": "integer" },
        "time": { "type": "string" },
        "testsuite": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/TestInfo"
          }
        }
      }
    },
    "TestInfo": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "file": { "type": "string" },
        "line": { "type": "integer" },
        "status": {
          "type": "string",
          "enum": ["RUN", "NOTRUN"]
        },
        "time": { "type": "string" },
        "classname": { "type": "string" },
        "failures": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Failure"
          }
        }
      }
    },
    "Failure": {
      "type": "object",
      "properties": {
        "failures": { "type": "string" },
        "type": { "type": "string" }
      }
    }
  },
  "properties": {
    "tests": { "type": "integer" },
    "failures": { "type": "integer" },
    "disabled": { "type": "integer" },
    "errors": { "type": "integer" },
    "timestamp": {
      "type": "string",
      "format": "date-time"
    },
    "time": { "type": "string" },
    "name": { "type": "string" },
    "testsuites": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/TestCase"
      }
    }
  }
}

The report uses the format that conforms to the following Proto3 using the
JSON encoding:

该报告使用符合以下 Proto3 的格式,使用JSON编码:

syntax = "proto3";

package googletest;

import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";

message UnitTest {
  int32 tests = 1;
  int32 failures = 2;
  int32 disabled = 3;
  int32 errors = 4;
  google.protobuf.Timestamp timestamp = 5;
  google.protobuf.Duration time = 6;
  string name = 7;
  repeated TestCase testsuites = 8;
}

message TestCase {
  string name = 1;
  int32 tests = 2;
  int32 failures = 3;
  int32 disabled = 4;
  int32 errors = 5;
  google.protobuf.Duration time = 6;
  repeated TestInfo testsuite = 7;
}

message TestInfo {
  string name = 1;
  string file = 6;
  int32 line = 7;
  enum Status {
    RUN = 0;
    NOTRUN = 1;
  }
  Status status = 2;
  google.protobuf.Duration time = 3;
  string classname = 4;
  message Failure {
    string failures = 1;
    string type = 2;
  }
  repeated Failure failures = 5;
}

For instance, the following program:以下代码为例

TEST(MathTest, Addition) { ... }
TEST(MathTest, Subtraction) { ... }
TEST(LogicTest, NonContradiction) { ... }

could generate this report:

{
  "tests": 3,
  "failures": 1,
  "errors": 0,
  "time": "0.035s",
  "timestamp": "2011-10-31T18:52:42Z",
  "name": "AllTests",
  "testsuites": [
    {
      "name": "MathTest",
      "tests": 2,
      "failures": 1,
      "errors": 0,
      "time": "0.015s",
      "testsuite": [
        {
          "name": "Addition",
          "file": "test.cpp",
          "line": 1,
          "status": "RUN",
          "time": "0.007s",
          "classname": "",
          "failures": [
            {
              "message": "Value of: add(1, 1)\n  Actual: 3\nExpected: 2",
              "type": ""
            },
            {
              "message": "Value of: add(1, -1)\n  Actual: 1\nExpected: 0",
              "type": ""
            }
          ]
        },
        {
          "name": "Subtraction",
          "file": "test.cpp",
          "line": 2,
          "status": "RUN",
          "time": "0.005s",
          "classname": ""
        }
      ]
    },
    {
      "name": "LogicTest",
      "tests": 1,
      "failures": 0,
      "errors": 0,
      "time": "0.005s",
      "testsuite": [
        {
          "name": "NonContradiction",
          "file": "test.cpp",
          "line": 3,
          "status": "RUN",
          "time": "0.005s",
          "classname": ""
        }
      ]
    }
  ]
}

{: .callout .important}
IMPORTANT: The exact format of the JSON document is subject to change.

重要提示:JSON文档的确切格式可能会发生变化。

Controlling How Failures Are Reported / 控制故障报告的方式

Detecting Test Premature Exit / 检测测试过早退出

Google Test implements the premature-exit-file protocol for test runners to
catch any kind of unexpected exits of test programs. Upon start, Google Test
creates the file which will be automatically deleted after all work has been
finished. Then, the test runner can check if this file exists. In case the file
remains undeleted, the inspected test has exited prematurely.

**谷歌测试实现了premature-exit-file协议,用于测试运行器捕获任何类型的测试程序的意外退出。**启动时,谷歌测试创建文件,在所有工作完成后将自动删除该文件。然后,测试运行程序可以检查这个文件是否存在。如果文件未被删除,则被检查的测试提前退出。

This feature is enabled only if the TEST_PREMATURE_EXIT_FILE environment
variable has been set.

只有设置了TEST_PREMATURE_EXIT_FILE环境变量,才会启用此功能。

Turning Assertion Failures into Break-Points / 将断言失败转换为断点

When running test programs under a debugger, it’s very convenient if the
debugger can catch an assertion failure and automatically drop into interactive
mode. GoogleTest’s break-on-failure mode supports this behavior.

当在调试器下运行测试程序时,如果调试器能够捕获断言失败并自动进入交互模式,那将非常方便。GoogleTest的break-on-failure模式支持这种行为。

To enable it, set the GTEST_BREAK_ON_FAILURE environment variable to a value
other than 0. Alternatively, you can use the --gtest_break_on_failure
command line flag.

要启用它,请将GTEST_BREAK_ON_FAILURE环境变量设置为非0的值。或者,你可以使用——gtest_break_on_failure命令行标志。

Disabling Catching Test-Thrown Exceptions / 禁止捕获测试抛出的异常

GoogleTest can be used either with or without exceptions enabled. If a test
throws a C++ exception or (on Windows) a structured exception (SEH), by default
GoogleTest catches it, reports it as a test failure, and continues with the next
test method. This maximizes the coverage of a test run. Also, on Windows an
uncaught exception will cause a pop-up window, so catching the exceptions allows
you to run the tests automatically.

GoogleTest可以启用例外,也可以不启用例外。如果测试抛出c++异常或(在Windows上)结构化异常(SEH),默认情况下GoogleTest会捕获它,报告为测试失败,然后继续执行下一个测试方法。这将最大化测试运行的覆盖率。此外,在Windows上,未捕获的异常将导致弹出窗口,因此捕获异常可以让你自动运行测试。

When debugging the test failures, however, you may instead want the exceptions
to be handled by the debugger, such that you can examine the call stack when an
exception is thrown. To achieve that, set the GTEST_CATCH_EXCEPTIONS
environment variable to 0, or use the --gtest_catch_exceptions=0 flag when
running the tests.

然而,在调试测试失败时,您可能希望由调试器处理异常,这样您就可以在抛出异常时检查调用堆栈。要实现这一点,请将GTEST_CATCH_EXCEPTIONS环境变量设置为0,或者在运行测试时使用——GTEST_CATCH_EXCEPTIONS =0标志。

Sanitizer Integration 洗手液一体化

The Undefined Behavior Sanitizer, Address Sanitizer,
and Thread Sanitizer all provide weak functions that you can override to trigger explicit failures when they detect sanitizer errors, such as creating a reference from nullptr. To override these functions, place definitions for them in a source file that you compile as part of your main binary:

未定义行为杀毒程序地址杀毒程序,和Thread Sanitizer都提供了弱函数,当它们检测到Sanitizer错误时,你可以覆盖它们以触发显式故障,例如从nullptr创建引用。要覆盖这些函数,请将它们的定义放在你编译成主二进制文件的源文件中:

extern "C" {
void __ubsan_on_report() {
  FAIL() << "Encountered an undefined behavior sanitizer error";
}
void __asan_on_error() {
  FAIL() << "Encountered an address sanitizer error";
}
void __tsan_on_report() {
  FAIL() << "Encountered a thread sanitizer error";
}
}  // extern "C"

After compiling your project with one of the sanitizers enabled, if a particular
test triggers a sanitizer error, GoogleTest will report that it failed.

在编译你的项目时启用了某个过滤程序,如果某个特定的测试触发了过滤程序错误,GoogleTest将报告它失败。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值