posts - 319, comments - 22, trackbacks - 0, articles - 11
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
搜索 
 对于  
V1_6_FAQ  
提示和常见问题关于谷歌 c + + 测试框架
zhanyong...@gmail.com更新的2011 年 4 月 18 日

如果你找不到在这里,你的问题的答案,你读过底漆AdvancedGuide,则将其发送到 googletestframework@googlegroups.com。

为什么应该的我最喜欢的 c + + 测试框架而不是使用 Google 测试?

首先,让我们说清楚我们不想要进入的 c + + 的测试框架是最佳的辩论。存在许多精细框架编写 c + + 的测试中,和我们有巨大的开发人员和用户他们尊重。我们认为不存在 (或者将) 最好的单一框架-您必须选择合适的工具为您正在处理的特定任务。

因为我们找不到正确的功能和便利条件组合在一个现有的框架,以满足我们的需要,我们创建了谷歌测试。以下是一个列表的事情,我们喜欢谷歌测试。我们不要为我们宣称他们是唯一谷歌测试-相反,他们使谷歌测试组合的选择。我们希望此列表可以帮助您决定是否为您太。

  • 谷歌测试旨在作为便携式: 它不需要异常或 RTTI ;围绕各种 bug 在各种编译器和环境 ; 它的工作原理等。因此,它适用于 Linux、 Windows、 Mac OS X 几个嵌入式的操作系统。
  • 非致命的断言 (EXPECT_ *) 已被证明是储户的大好时机,因为它们允许在单个编辑-编译-测试周期中报告多个故障的测试。
  • 很容易写生成信息性消息的断言: 您只使用流语法追加任何附加信息,如ASSERT_EQ (5,Foo(i)) <<"where i ="<< i ;它不需要一套新的宏或特殊功能。
  • 谷歌测试自动检测您的测试,并且不需要您枚举它们为了运行它们。
  • 死亡测试是非常方便,确保您断言在生产中的代码由合适的条件触发的。
  • SCOPED_TRACE可以帮助您理解断言失败的上下文时它来自内部是子路径或循环。
  • 您可以决定要使用的名称模式运行的测试。这样可以节省的时间,当您要快速地重复测试失败。
  • 谷歌测试可以生成可以像哈德逊流行连续生成系统所分析的 XML 测试结果报告。
  • 简单的东西很容易在谷歌测试中,而硬的事情都是可能: 此外,高级的功能 (如全球测试环境和测试参数的类型,谷歌测试支持扩展框架--谷歌测试做不出的框中,如果用户通过各种方式可能就一个用户可以实现使用谷歌测试公共 API 的功能而无需更改 Google 测试本身。特别是,您可以:

谷歌测试将您修复它们进行编译时收到警告?

我们的努力减少谷歌测试生成编译器警告。发布一个新版本之前, 我们测试以确保它不会生成 Windows、 Linux、 Mac OS 上使用它的 CMake 脚本在编译时警告。

不幸的是,这并不意味着你保证就看到没有任何警告,谷歌测试您的环境中进行编译时:

  • 您可能使用不同的编译器为我们使用或同一编译器的不同版本。我们可能不能测试所有的编译器。
  • 您可以在不同平台上像我们一样编制。
  • 像我们一样,可能您的项目使用不同的编译器标志。

它并不总是可能使谷歌测试无预警的每个人。或者,它可能不可取如果很少启用警告并修复侵犯行为会使代码更复杂。

如果谷歌测试进行编译时,您会看到警告,我们建议您在使用-isystem标志 (假设你使用 GCC) 来标记为系统标题谷歌测试头。这会取消警告从谷歌测试邮件头。

为什么应该不测试用例名称和测试名称包含下划线?

下划线 (_) 是特殊的情况下,c + + 储备由编译器和标准库使用下列:

  1. 任何以大写字母,跟着_开头的标识符和
  2. 任何标识符的容器两个连续下划线 (即__)任意位置在其名称中。

用户代码是禁止使用这样的标识符。

现在让我们看看这意味着测试TEST_F.

目前测试 TestName TestCaseName) ,将生成一个名为TestCaseName_TestName_Test类。如果包含TestCaseNameTestName ,会发生什么_?

  1. 如果TestCaseName开头_跟着以大写字母 (比如_Foo),我们最终_Foo_TestName_Test,这是保留,因此无效。
  2. 如果TestCaseName _ (比如Foo_) 以结尾,我们得到Foo__TestName_Test,而是无效。
  3. 如果TestName开头_ (比如_Bar),我们得到TestCaseName__Bar_Test,而是无效。
  4. 如果TestName _ (比如Bar_) 以结尾,我们得到TestCaseName_Bar__Test,而是无效。

TestCaseNameTestName不能开始或结束_与如此清晰 (事实上, TestCaseName可以开始_ — — 只要_不跟着大写字母。但是,变得更复杂。所以为了简单起见,我们只是说它不能以开始_.).

它可能是TestCaseNameTestName ,包含在中间_好的。但是,考虑这:

TEST(Time, Flies_Like_An_Arrow) { ... }
TEST
(Time_Flies, Like_An_Arrow) { ... }

现在,两个测试s 都将生成相同的类 (Time_Files_Like_An_Arrow_Test)。这不是好的。

所以为了简单起见,我们只是要求用户,以避免在TestCaseNameTestName _ 。规则是不必要的更多限制,但它既简单又容易记住。它还使谷歌测试以防其执行需要在将来会改变一些发展的空间。

如果您违反此规则,有可能不会马上的后果,但您的测试可能 (只是 5 月) 与新的编译器 (或新版本的编译器使用的) 或新版本的谷歌测试中断。因此最好遵循的规则。

它为什么不推荐将安装谷歌测试预编译的副本 (例如,为 /usr/local)?

在最初的时候,我们说过你也可以安装已编译的谷歌测试库使用使安装*nix 系统。然后每个用户的计算机中,可以编写测试,无需重新编译谷歌测试。

这看起来像是一个好主意,但它有了茶: 每个用户需要编译使用同一编译器标志用于编译安装的谷歌测试库 ; 他测试否则他可能遇到未定义的行为 (即测试可以奇怪的行为和甚至可能会崩溃,没有明显的原因)。

为什么会这样?因为 c + + 都有这种东西叫做一个定义规则: 如果两个 c + + 源文件包含不同定义的同一类/功能/变量,并且您将它们链接在一起,你违反规则。链接器可能或不可能捕获错误 (在许多情况下它不需要由 c + + 标准赶上违反)。如果不是,你会得到奇怪的运行时行为,是意外,很难调试。

如果您编译谷歌测试和测试代码使用不同的编译器标志,他们可能会看到不同的定义的同一类/功能/变量 (如, # if谷歌测试中使用)。因此,头脑清楚,我们建议以避免安装预编译的谷歌测试库。相反,每个项目应编译谷歌测试本身,这样它可以肯定的是同一标志用于谷歌测试和测试。

我如何生成 64 位二进制文件在 Windows 上 (使用 Visual Studio 2008)?

(由特雷弗 · 罗宾逊回答)

加载提供的 Visual Studio 解决方案文件,或msvc\gtest md.slnmsvc\gtest.sln经过迁移向导迁移到 Visual Studio 2008 的解决方案和项目文件。生成菜单中选择配置管理器 … … 。活动解决方案平台下拉列表中选择> < 新 … … 。从新的平台下拉列表中选择x 64 ,将从此处复制设置设置保留为Win32创建新的项目平台选中此选项,然后单击确定现在,您有Win32x64平台配置,可以选择从标准工具栏上,使您可以构建 32 位或 64 位的二进制文件 (或两者在一次使用批量生成) 之间切换。

为了防止覆盖另一个生成输出文件,您需要更改所有项目之间的中间目录设置为新创建的平台配置。为此,多选操作 (如使用按住 shift 键单击) 的所有项目 (但不是解决办法)解决方案资源管理器中。用鼠标右键单击其中之一,并选择属性在左窗格中,选择配置属性,并从配置下拉列表中,选择所有配置请确保选定的平台是x 64中间目录设置,更改从$(PlatformName)\$(ConfigurationName)$(OutDir)\$(ProjectName)的值。单击确定,然后生成解决方案。生成完成时,64 位二进制文件将在msvc\x64\Debug目录中。

可以在 MinGW 上使用谷歌测试吗?

我们没有测试此自己,但每个亚伯拉罕森报告说他是能够编译和安装谷歌测试成功地使用这个软件从 MinGW 时。您需要将其与配置:

配置路径/TO/CC ="海湾合作委员会 mno-这个软件"CXX ="g + +-mno-这个软件"

您应该能够取代-mno-这个软件选项以直接链接到真正的 MinGW 二进制文件,但我们还没试过。

注意事项:

  • 在编译时,很多警告。
  • 谷歌测试本身并不是所有的测试都兼容 MinGW使检查会产生一些错误。

我们亦在 Linux 上包含站点上使用这些说明成功交叉编译的谷歌测试 MinGW 二进制文件的报告。

请如果您有兴趣提高对 MinGW 的支持,联系googletestframework@googlegroups.com 。

为什么谷歌测试支持 EXPECT_EQ ptr NULL) 和 ASSERT_EQ ptr NULL) 但不是 EXPECT_NE ptr NULL) 和 ASSERT_NE ptr NULL)?

由于 c + + 的一些特性,它需要一些非普通模板元编程技巧,支持使用NULL作为参数的EXPECT_XX()ASSERT_XX()宏。因此我们只能做到哪里最需要 (否则我们让谷歌测试执行难维持与比必要多出错)。

EXPECT_EQ()宏需要作为其第一个参数的预期值和实际值作为第二个。这是合理的有人想要写EXPECT_EQ NULL some_expression),并确实要求这样做几次。因此我们执行它。

EXPECT_NE ptr NULL)需要并不是几乎一样强壮。当断言失败时,您已经知道该ptr必须为,因此它不会添加任何信息,在此情况下打印 ptr。这意味着, EXPECT_TRUE(ptr!NULL)同样适用。

如果我们支持EXPECT_NE ptr NULL),我们将不得不支持EXPECT_NE (ptr,NULL)以及一致性,作为与EXPECT_EQ,不同的是我们还没有一项公约EXPECT_NE的两个参数的顺序。这意味着使用模板元编程技巧在执行两次,使其更难以理解和维护。我们相信效益并不证明成本。

最后,随着谷歌模仿图书馆的增长,我们鼓励人们更经常在测试中使用统一的EXPECT_THAT (值) 和语法。研究方法的一个显著的优势是匹配可以轻松地结合形式新匹配,而是EXPECT_NE等,宏不能轻松地组合。因此,我们希望更多投资比匹配,在EXPECT_XX()宏。

谷歌测试支持并行运行测试吗?

测试赛跑者往往紧耦合与生成/测试环境,和谷歌测试不会尝试解决问题以并行方式运行测试。相反,我们试图使谷歌测试与试验赛跑者很好地工作。例如,谷歌测试 XML 报表包含对每个测试,花费的时间,其gtest_list_testsgtest_filter的标志可用于拆分到多个进程执行的测试方法。这些功能可以帮助并行运行的测试的测试运行。

为什么不要谷歌测试运行不同的线程中的测试速度的东西?

很难写线程安全的代码。大多数测试线程安全,不会写入,因此可能无法正常工作在多线程环境中。

如果你想一想,它已经难使您的代码时你知道其他线程做什么工作。它是艰难得多,有时甚至是不可能的以使您的代码时,你不知道的其他线程正在做工作 (记住可以添加、 删除或修改之后写入您的测试试验方法)。如果您要运行的测试的同时,你会在不同的进程中更好地运行它们。

为什么谷歌测试断言不执行使用异常?

我们的原始动机是为了能够禁用例外的项目中使用谷歌测试。后来我们意识到这种方法的一些额外的好处:

  1. 在析构函数中投掷是 c + + 中未定义的行为。不使用异常意味着谷歌测试断言是安全的在析构函数中使用。
  2. EXPECT_ *家庭的宏将甚至出现故障,会报告一次运行试验中允许多个故障后继续。这是一个受欢迎的功能、 作为 c + + 中编辑-编译-测试周期通常是很长,能够修复一次超过一件事是一种幸福。
  3. 如果使用异常实施断言,测试虚假可能会忽略失败如果它抓住用户代码:
  4. try { ... ASSERT_TRUE(...) ... }
    catch (...) { ... }

上面的代码会通过即使ASSERT_TRUE抛出。虽然有人写此测试中的机会不大,很可能会遇到这种模式,当你写下测试的代码的调用的回调的断言。

不使用异常的缺点在于ASSERT_ * (实施使用返回) 将只中止当前函数,不当前测试.

为什么我们两个不同的宏用测试与无固定装置?

不幸的是,c + + 的宏观系统不允许我们为这两种情况使用相同的宏。一种可能性是以提供测试夹具、 只有一个宏,要求用户有时定义为空的夹具:

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

TEST_F
(FooTest, DoesThis) { ... }

typedef ::testing::Test FooTest;

TEST_F
(FooTest, DoesThat) { ... }

然而,很多人认为这是一条线太多。:-)我们的目标是使它真的很容易写测试,所以我们试图使琐碎创建简单的测试。这意味着需要为此类测试使用一个单独的宏。

我们认为这两种方法是理想的但其中一方是合理的。最后,它可能并不重要太多。

我们为什么不利用结构作为测试夹具?

我们要表示被动的数据时,才使用结构。这种结构和类之间的区别是良好记录的代码作者的意图。由于测试夹具如SetUp()TearDown()的逻辑,它们更好地定义为类。

死亡测试试验转轮和使用断言作为实施为什么呢?

我们的目标是使死亡测试,方便用户可能是 c + + 允许。特别是:

  • 转轮式需要拆分成两个部分的信息: 死亡的定义测试本身和转轮如何运行死亡测试和所期望的规范。将 c + + 程序写死亡测试,虽然转轮规范可能或不可能。用户需要小心地保持两个同步。ASSERT_DEATH 语句 expected_message)在一个地方,在一种语言,而无需样板代码中指定所需的所有信息。它是非常声明性。
  • ASSERT_DEATH有一个类似语法和其他谷歌测试的断言,错误报告的语义,因此容易学。
  • ASSERT_DEATH可以混入其它断言和其他逻辑,在你的意志。你并不限于一人死亡测试每个测试方法。例如,您可以编写类似:
  •     if (FooCondition()) {
          ASSERT_DEATH
    (Bar(), "blah");
       
    } else {
          ASSERT_EQ
    (5, Bar());
       
    }

如果您希望一个死亡测试每个测试方法,您可以编写您的测试中那种风格,但我们不想,强加给用户。更少的人工限制越好。

  • ASSERT_DEATH可以引用当前函数中的局部变量,您可以决定多少死亡测试要基于的运行时信息。例如,
  •     const int count = GetCount();  // Only known at run time.
       
    for (int i = 1; i <= count; i++) {
          ASSERT_DEATH
    ({
           
    double* buffer = new double[i];
           
    ... initializes buffer ...
           
    Foo(buffer, i)
         
    }, "blah blah");
       
    }

基于转轮的方法往往是更为静态和不够灵活,或需要更多的用户作出努力,得到这种灵活性。

ASSERT_DEATH另一个有意思的一点是它调用fork()创建一个子进程运行死亡测试。这减轻快速、 fork()使用写入时复制页面,并会导致几乎为零的开销,并从用户提供语句直接跳过所有全局和本地初始化和给定的语句导致任何代码启动的子进程。如果您启动子进程从零开始,它可以秒只加载的一切并开始运行如果测试动态链接到许多图书馆。

我的死亡测试修改某些状态,但死亡测试完成后,更改好像是迷路了。为什么会这样?

执行死刑测试 (EXPECT_DEATH等) 在子流程世倜预期的崩溃不会杀死测试程序 (即父进程)。因此,他们承担任何内存中副作用是流星雨在它们各自的子流程,但不是在父进程。你可以把它们看作运行的平行宇宙,更多或更少。

编译器抱怨"未定义的引用"到一些静态的 const 成员变量,但我确实在类体中定义它们。怎么了?

如果您的类有一个静态数据成员:

// foo.h
class Foo {
 
...
 
static const int kBar = 100;
};

您还需要在foo.cc中定义它以外的类的主体:

const int Foo::kBar;  // No initializer here.

否则为你的代码是无效的 c + +,并以出乎意料的方式可能会中断。特别是,在谷歌测试比较断言 (EXPECT_EQ等) 中使用它将生成一个"未定义的引用"链接器错误。

我必须具有几个实现的接口。可以一次写入一组测试和所有实现都重复他们吗?

Google Test doesn't yet have good support for this kind of tests, or data-driven tests in general. We hope to be able to make improvements in this area soon.

Can I derive a test fixture from another?

Yes.

Each test fixture has a corresponding and same named test case. This means only one test case can use a particular fixture. Sometimes, however, multiple test cases may want to use the same or slightly different fixtures. For example, you may want to make sure that all of a GUI library's test cases don't leak important system resources like fonts and brushes.

In Google Test, you share a fixture among test cases by putting the shared logic in a base test fixture, then deriving from that base a separate fixture for each test case that wants to use this common logic. You then use TEST_F() to write tests using each derived fixture.

Typically, your code looks like this:

// Defines a base test fixture.
class BaseTest : public ::testing::Test {
 
protected:
   
...
};

// Derives a fixture FooTest from BaseTest.
class FooTest : public BaseTest {
 
protected:
   
virtual void SetUp() {
     
BaseTest::SetUp();  // Sets up the base fixture first.
     
... additional set-up work ...
   
}
   
virtual void TearDown() {
     
... clean-up work for FooTest ...
     
BaseTest::TearDown();  // Remember to tear down the base fixture
                             
// after cleaning up FooTest!
   
}
   
... functions and variables for FooTest ...
};

// Tests that use the fixture FooTest.
TEST_F
(FooTest, Bar) { ... }
TEST_F
(FooTest, Baz) { ... }

... additional fixtures derived from BaseTest ...

If necessary, you can continue to derive test fixtures from a derived fixture. Google Test has no limit on how deep the hierarchy can be.

完整的示例,使用派生的试验装置,请参见sample5.

我的编译器抱怨"无效值不忽视,应该是"。这是什么意思?

你可能不返回void函数中用ASSERT_*() 。ASSERT_*()可以只用void函数中。

我的死亡测试挂起 (或赛格故障)。如何解决呢?

在谷歌测试中,死亡测试运行在一个子进程中,他们的工作的方式是微妙。写你确实需要了解他们是如何死亡的测试。请确保您已经阅读这。

特别是,死亡测试不喜欢父进程中有多个线程。所以您可以尝试的第一件事是消除创建线程以外的EXPECT_DEATH().

有时这是不可能,您必须使用一些图书馆可能会创建线程之前甚至达到main () 。在这种情况下,您可以尝试通过移动尽可能多的活动在EXPECT_DEATH()内尽可能减少冲突的可能性 (极端情况下,您希望移动内部的一切),或离开它尽可能多的东西。另外,可以将死亡测试样式设置为"线程",而是更安全,但速度较慢,请尝试并查看是否它会帮助。

如果你去使用线程安全死亡测试,请记住它们会重新运行测试程序从子进程中开始。因此请确保您的程序可以运行肩并肩与本身是确定性。

最后,要归结为好的并发编程。你要确保这是没有争用条件或死锁在你的程序中。没有银弹-对不起 !

应该使用构造函数/析构函数测试夹具或设置上/泪下功能吗?

要记住的第一件事是谷歌测试不会重用相同的测试夹具对象在多个测试。每个TEST_F,谷歌测试将创建新测试夹具对象,立即调用SetUp(),运行测试,调用TearDown(),然后立即删除测试夹具的对象。因此,有不需要编写SetUp()TearDown()函数如果构造函数或析构函数已经完成的工作。

您仍可能需要使用SetUp()/TearDown()在以下情况中:

  • 如果撤展操作可能会引发异常,则必须使用TearDown()析构函数,相对于扔在析构函数中会导致未定义的行为,通常会立刻杀死你的程序。请注意,编译器中启用异常时,可能会引发许多标准库 (STL) 像。因此如果你想写工作有无异常的便携式测试应该更喜欢TearDown() 。
  • 谷歌测试团队正考虑制作平台上抛出的异常在哪里的断言宏启用 (例如 Windows、 Mac OS、 Linux 客户端),其中,将不再需要传播到它的调用子例程从失败的用户。因此,您不应该使用谷歌测试断言在析构函数中的,如果您的代码可以在这样的平台上运行。
  • 在构造函数或析构函数中,你不能在此对象上调用虚函数。(您可以调用一个方法声明为虚拟的但它将静态绑定)。因此,如果您需要调用将被派生类中的重写的方法,您必须使用SetUp()/TearDown().

编译器抱怨"没有匹配的调用的函数"何时使用 ASSERT_PREDn。如何解决呢?

如果您使用ASSERT_PRED *EXPECT_PRED *中的谓词函数重载或模板,编译器将有麻烦弄哪一个重载的版本,它应该使用。ASSERT_PRED_FORMAT *EXPECT_PRED_FORMAT *没有这个问题。

如果您看到此错误,您可能要切换到(ASSERT|期待) _PRED_FORMAT *,它也会给你更好的失败消息。如果,不过,这不是一个选项,您可以通过明确告诉编译器来挑哪个版本来解决问题。

例如,假设您有

bool IsPositive(int n) {
 
return n > 0;
}
bool IsPositive(double x) {
 
return x > 0;
}

如果你写,你将得到编译器错误。

EXPECT_PRED1(IsPositive, 5);

不过,这会工作:

EXPECT_PRED1(*static_cast<bool (*)(int)>*(IsPositive), 5);

Static_cast运算符尖括号里面的东西是int函数指针的类型- IsPositive().)

另一个例子是,当你有一个模板函数

template <typename T>
bool IsNegative(T x) {
 
return x < 0;
}

您可以使用它在谓词的断言,像这样:

ASSERT_PRED1(IsNegative*<int>*, -5);

东西都更有趣,如果您的模板有多个参数。不会编译:

ASSERT_PRED2(*GreaterThan<int, int>*, 5, 0);

作为 c + + 预处理器认为你给ASSERT_PRED2 4 参数,这是一个超过预期。解决方法是将谓词函数的包装中括号:

ASSERT_PRED2(*(GreaterThan<int, int>)*, 5, 0);

我的编译器抱怨"忽略返回值"当我打电话 RUN_ALL_TESTS()。为什么会这样?

有些人所忽略的返回值RUN_ALL_TESTS()也就是说,而不是

return RUN_ALL_TESTS();

他们写道

RUN_ALL_TESTS();

这是错误和危险的。测试转轮需要看到RUN_ALL_TESTS()的返回值,以确定是否测试通过。如果您的main ()函数将忽略它,您的测试将被视为成功即使有谷歌测试断言失败。很差。

为了帮助用户避免这种危险的 bug, RUN_ALL_TESTS()的执行导致 gcc 提高此警告,当返回值将被忽略。如果您看到此警告,此修复程序很简单: 只需确保其值用作main ()的返回值.

我的编译器抱怨构造函数 (或析构函数) 不能返回值。这是怎么回事?

由于 c + +,为了支持流媒体消息ASSERT_ *,如语法的一个特色,

ASSERT_EQ(1, Foo()) << "blah blah" << foo;

我们不得不放弃使用ASSERT *失败 * (但不是期望 * ADD_FAILURE *) 中构造函数和析构函数。解决方法是将构造函数/析构函数的内容移至私人无效成员函数,或如果切换到EXPECT_*() 。本节中的用户指南解释了它。

不是我的设置功能。为什么会这样?

C + + 是区分大小写。它应拼写为SetUp()你拼写它作为Setup()?

同样地,有时拼写为SetupTestCase() SetUpTestCase()的人,不知道为什么它永远不会被称为。

我如何做直接在 Emacs 失败的行跳?

谷歌测试失败的邮件格式是 Emacs 和许多其他 Ide,像 acme 和 XCode 理解。如果在编译缓冲区中 Emacs 谷歌测试邮件,则可点击。你现在可以打上一条消息要跳转到对应的源代码,输入或使用C x ' 要跳转到下一次的失败。

我有几个测试用例,共享相同的测试夹具逻辑,有一个新的测试夹具类定义为每个吗?这看起来非常繁琐。

你不必。而不是

class FooTest : public BaseTest {};

TEST_F
(FooTest, Abc) { ... }
TEST_F
(FooTest, Def) { ... }

class BarTest : public BaseTest {};

TEST_F
(BarTest, Abc) { ... }
TEST_F
(BarTest, Def) { ... }

您可以只是typedef测试夹具:

typedef BaseTest FooTest;

TEST_F
(FooTest, Abc) { ... }
TEST_F
(FooTest, Def) { ... }

typedef BaseTest BarTest;

TEST_F
(BarTest, Abc) { ... }
TEST_F
(BarTest, Def) { ... }

谷歌测试输出,埋在一大堆的日志消息。我该怎么办?

谷歌测试输出注定要简明和人性化的报告。如果您的测试生成的文本输出本身,它将混合与谷歌测试输出,从而很难阅读。然而,有一个简单的解决方案,这一问题。

由于大多数日志消息转到 stderr,我们决定让谷歌测试输出到标准输出。这种方式,可以方便地分隔两个使用重定向。例如:

./my_test > googletest_output.txt

为什么应该在全局变量喜欢测试夹具?

有几个好的理由:

  1. 很可能你的测试需要更改其全局变量的状态。这使得难以逃脱一个测试和其他污染,难以调试跟副作用。通过使用固定装置,每次测试了一套新的变量的不同 (但具有相同的名称)。因此,保持彼此独立的测试。
  2. 全局变量污染全局命名空间。
  3. 可重用测试夹具通过子类,其中做不容易全局变量。这很有用,如果很多测试用例有一些共同点。

如何测试而无需编写 FRIEND_TEST () s 的私有类成员?

您应尝试写入可测试代码,这意味着类应从他们的公共接口轻松地进行测试。要实现这一目标的一种是平普尔成语: 你将所有的一类的私有成员移动到帮助器类,并公开的帮助器类的所有成员。

你有几个其他选项,不需要使用FRIEND_TEST:

  • 写入测试夹具类的成员为:
  • class Foo {
     
    friend class FooTest;
     
    ...
    };

    class FooTest : public ::testing::Test {
     
    protected:
     
    ...
     
    void Test1() {...} // This accesses private members of class Foo.
     
    void Test2() {...} // So does this one.
    };

    TEST_F
    (FooTest, Test1) {
     
    Test1();
    }

    TEST_F
    (FooTest, Test2) {
     
    Test2();
    }
  • 在夹具类中,写的访问器用于测试的类的私有成员,然后在您的测试中使用访问器:
  • class Foo {
     
    friend class FooTest;
     
    ...
    };

    class FooTest : public ::testing::Test {
     
    protected:
     
    ...
      T1 get_private_member1
    (Foo* obj) {
       
    return obj->private_member1_;
     
    }
    };

    TEST_F
    (FooTest, Test1) {
     
    ...
      get_private_member1
    (x)
     
    ...
    }
  • 如果将方法声明为受保护,您可以更改其仅仅用于测试的子类中的访问级别:
  • class YourClass {
     
    ...
     
    protected: // protected access for testability.
     
    int DoSomethingReturningInt();
     
    ...
    };

    // in the your_class_test.cc file:
    class TestableYourClass : public YourClass {
     
    ...
     
    public: using YourClass::DoSomethingReturningInt; // changes access rights
     
    ...
    };

    TEST_F
    (YourClassTest, DoSomethingTest) {
     
    TestableYourClass obj;
      assertEquals
    (expected_value, obj.DoSomethingReturningInt());
    }

如何测试而无需编写 FRIEND_TEST () s 的私有类的静态成员?

我们发现私有静态方法杂波的头文件。他们是实现细节,理想情况下应保持出。 h。所以常常我让他们转而无功能。

而不是:

// foo.h
class Foo {
 
...
 
private:
 
static bool Func(int n);
};

// foo.cc
bool Foo::Func(int n) { ... }

// foo_test.cc
EXPECT_TRUE
(Foo::Func(12345));

您可能应该更好地编写:

// foo.h
class Foo {
 
...
};

// foo.cc
namespace internal {
 
bool Func(int n) { ... }
}

// foo_test.cc
namespace internal {
 
bool Func(int n);
}

EXPECT_TRUE
(internal::Func(12345));

我想要使用不同的参数运行测试几次。我需要写几个类似的副本吗?

您可以使用一个称为功能 [V1_6_AdvancedGuide# Value_Parameterized_Tests 的值参数测试] 让您没有定义它不止一次重复使用不同的参数,您的测试。

如何测试文件,它定义 main ()?

若要测试一个foo.cc文件,您需要编译并链接到您的单元测试程序。然而,当文件包含main ()函数的定义,它与你的单元测试的main ()将会发生冲突,并将导致生成错误。

选择合适的解决方案是将它分成三个文件:

  1. foo.h包含声明,
  2. foo.cc包含main (),除了定义和
  3. foo_main.cc定义的main ()只包含.

然后,可以很容易测试foo.cc 。

如果您正在将测试添加到现有文件并不愿意看到这样的侵入性变化,有黑客: 只是在单元测试中包含整个foo.cc文件。例如:

// File foo_unittest.cc

// The headers section
...

// Renames main() in foo.cc to make room for the unit test main()
#define main FooMain

#include "a/b/foo.cc"

// The tests start here.
...

但是,请记住这是黑客,只应作为最后的手段。

ASSERT_DEATH() 中的语句参数可以是什么?

ASSERT_DEATH _regex_ _statement_)(或任何死亡断言宏) 可以使用_statement_在哪里有效。所以基本上_statement_可以是任何在当前上下文中有意义的 c + + 语句。特别是,它可以引用全局和/或本地变量,并且可以是:

  • 一个简单的函数调用 (通常情况下),
  • 一个复杂的表达式,或
  • 复合语句。

这里显示了一些示例:
// A death test can be a simple function call.
TEST
(MyDeathTest, FunctionCall) {
  ASSERT_DEATH
(Xyz(5), "Xyz failed");
}

// Or a complex expression that references variables and functions.
TEST
(MyDeathTest, ComplexExpression) {
 
const bool c = Condition();
  ASSERT_DEATH
((c ? Func1(0) : object2.Method("test")),
               
"(Func1|Method) failed");
}

// Death assertions can be used any where in a function. In
// particular, they can be inside a loop.
TEST
(MyDeathTest, InsideLoop) {
 
// Verifies that Foo(0), Foo(1), ..., and Foo(4) all die.
 
for (int i = 0; i < 5; i++) {
    EXPECT_DEATH_M
(Foo(i), "Foo has \\d+ errors",
                   
::testing::Message() << "where i is " << i);
 
}
}

// A death assertion can contain a compound statement.
TEST
(MyDeathTest, CompoundStatement) {
 
// Verifies that at lease one of Bar(0), Bar(1), ..., and
 
// Bar(4) dies.
  ASSERT_DEATH
({
   
for (int i = 0; i < 5; i++) {
     
Bar(i);
   
}
 
},
 
"Bar has \\d+ errors");}

googletest_unittest.cc包含更多的例子,如果你感兴趣。

ASSERT_DEATH 使用正则表达式什么语法?

在 POSIX 系统上,谷歌测试使用 POSIX 扩展正则表达式语法 (http://en.wikipedia.org/wiki/Regular_expression#POSIX_Extended_Regular_Expressions)。在 Windows 上,它使用正则表达式语法的有限变体。有关更多详细信息,请参见 [V1_6_AdvancedGuide# Regular_Expression_Syntax 正则表达式语法]。

我有一个夹具类美孚,但 TEST_F (美孚、 栏) 给了我错误"对 Foo::Foo() 的调用不匹配功能"。为什么会这样?

谷歌测试需要能够创建对象的测试夹具类中,因此它必须具有默认构造函数。通常,编译器将定义一个给你。但是,有些情况下,你也要定义您自己:

  • 如果显式声明类美孚的非默认构造函数,然后您需要定义默认构造函数,即使是不为空。
  • 如果美孚具有 const 非静态数据成员,则您必须定义默认构造函数,以初始化 const 成员的构造函数初始值设定项列表中。(早期版本的gcc不会强制您对 const 成员进行初始化。它是一个gcc 4中已修复的 bug.)

ASSERT_DEATH 为什么抱怨以前的线程都已加入?

随着 Linux pthread 库中,没有转回一旦你越线从单个线程对多个线程。您创建的线程,第一次管理器创建一个线程是此外,因此您可以获得 3,不 2,线程。以后,当您创建的线程时加入主线程的线程计数递减 1,但管理器线程将永远不会被杀,所以你还有两个线程,这意味着您不能安全地运行死亡测试。

新 NPTL 线程库不会患这个问题,因为它不会创建一个管理器线程。但是,如果你无法控制哪台计算机运行您的测试,你不应该取决于此。

为什么谷歌测试是否需要整个测试用例,而不是要被命名为 FOODeathTest,使用 ASSERT_DEATH 时的各个测试的?

谷歌测试并不交叉来自不同测试用例的测试。就是它第一,在一个测试用例中运行所有测试,然后都运行所有测试下一个测试用例,依此类推。谷歌测试这样做是因为它需要之前它的第一次测试运行时,设置了一个测试用例和 afterwords 拆了。分裂测试用例需要多个设置和撤展过程,这是效率低下,令语义不洁净。

如果我们确定的顺序基于测试的测试用例的名称而不是名称的测试,我们将会有以下的情况的问题:

TEST_F(FooTest, AbcDeathTest) { ... }
TEST_F
(FooTest, Uvw) { ... }

TEST_F
(BarTest, DefDeathTest) { ... }
TEST_F
(BarTest, Xyz) { ... }

由于FooTest.AbcDeathTest需要运行BarTest.Xyz之前,我们不隔行扫描来自不同测试用例的测试,我们需要在BarTest案中运行任何测试之前运行生成器的情况的全部测试。要运行BarTest.DefDeathTest FooTest.Uvw之前的规定发生矛盾.

但我不喜欢它包含死亡测试和非死亡测试时调用我整个测试用例 FOODeathTest。我该怎么办?

你不需要,但如果你愿意,你可能分裂测试用例,生成器FooDeathTest,名字哪里弄清楚他们与相关:

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

TEST_F
(FooTest, Abc) { ... }
TEST_F
(FooTest, Def) { ... }

typedef FooTest FooDeathTest;

TEST_F
(FooDeathTest, Uvw) { ... EXPECT_DEATH(...) ... }
TEST_F
(FooDeathTest, Xyz) { ... ASSERT_DEATH(...) ... }

编译器抱怨"不敌运算符 << '"何时使用断言。是什么给了?

如果您使用用户定义类型FooType的说法,你必须确保有输出 & 运算符 << (输出 & const FooType &)定义,我们可以打印的FooType值的函数.

此外,如果在名称空间中,声明为FooType <<运算符还需要在同一命名空间中定义。

我如何压抑对 Windows 的内存泄漏消息?

由于静态初始化的谷歌测试单身人士需要在堆上的分配,Visual c + + 内存泄漏检测仪将报告在程序运行结束时的内存泄漏问题。为避免这种最简单的方法是使用_CrtMemCheckpoint_CrtMemDumpAllObjectsSince ,不报告任何静态调用初始化堆对象。有关更多详细信息和附加堆检查/调试例程,请参阅 MSDN。

我工程与谷歌在 Visual Studio 中的测试,我收到的都是一堆链接器错误 (或警告)。帮助!

你可以得到以下链接器的一些错误或警告如果您试图链接您的测试项目与谷歌测试库时,您的项目不生成使用相同的编译器设置。

  • LNK2005: 符号已经定义的对象
  • LNK4217: 本地定义符号导入功能 '功能' ' 符号
  • LNK4049: 本地定义符号 '符号' 导入

谷歌测试项目 (gtest.vcproj) 已将运行时库选项设置为 /MT (使用多线程静态库,用于调试 /MTd)。如果您的项目使用别的东西,例如 /MD (使用 /MDd 用于调试多线程的 Dll),您需要更改以匹配您的项目中谷歌测试项目的设置。

更新此设置打开项目属性在 Visual Studio IDE 中,然后选择配置属性的分支 |C/C + + |代码生成,并更改"运行时库"的选项。您还可以尝试使用 gtest md.vcproj 而不 gtest.vcproj。

在库中,我把我的测试中,Google 测试并不运行它们。发生了什么事情?

你读过谷歌测试底漆页上警告吗?

我希望与 Visual Studio 一起使用谷歌测试,但不知道从哪里开始。

许多人都在您所在的位置和张贴之一他到我们的邮件列表中的解决方案。这里是他的链接: http://hassanjamilahmad.blogspot.com/2009/07/gtest-starters-help.html.

我看到了编译一提 std::type_traits 尝试在 Solaris 上使用谷歌测试时的错误。

谷歌测试使用 c + + 标准库不支持 SunStudio 的部分。我们的用户报告使用替代实现成功。尝试运行生成后运行此命令:

导出抄送 = 抄送 CXX = 抄送 CXXFLAGS ='-库 = stlport4'

我的代码如何检测其是否运行在测试中?

如果您编写代码,嗅是否它运行在测试中,并且相应地做不同的事情,渗入生产代码仅测试逻辑和有没有捷径,确保仅测试的代码路径不误生产中运行。这种聪明也会导致Heisenbugs因此,我们强烈建议对实践,和谷歌测试并不提供一种方法做这件事。

In general, the recommended way to cause the code to behave differently under test is dependency injection. You can inject different functionality from the test and from the production code. Since your production code doesn't link in the for-test logic at all, there is no danger in accidentally running it.

However, if you reallyreallyreally have no choice, and if you follow the rule of ending your test program names with _test, you can use thehorrible hack of sniffing your executable name (argv[0] in main()) to know whether the code is under test.

Google Test defines a macro that clashes with one defined by another library. How do I deal with that?

In C++, macros don't obey namespaces. Therefore two libraries that both define a macro of the same name will clash if you #include both definitions. In case a Google Test macro clashes with another library, you can force Google Test to rename its macro to avoid the conflict.

Specifically, if both Google Test and some other code define macro FOO, you can add

  -DGTEST_DONT_DEFINE_FOO=1

to the compiler flags to tell Google Test to change the macro's name from FOO to GTEST_FOO. For example, with -DGTEST_DONT_DEFINE_TEST=1, you'll need to write

  GTEST_TEST(SomeTest, DoesThis) { ... }

instead of

  TEST(SomeTest, DoesThis) { ... }

in order to define a test.

Currently, the following TESTFAILSUCCEED, and the basic comparison assertion macros can have alternative names. You can see the full list of covered macros here. More information can be found in the "Avoiding Macro Name Clashes" section of the README file.

My question is not covered in your FAQ!

If you cannot find the answer to your question in this FAQ, there are some other resources you can use:

  1. read other wiki pages,
  2. search the mailing list archive,
  3. ask it on googletestframework@googlegroups.com and someone will answer it (to prevent spam, we require you to join the discussion groupbefore you can post.).

Please note that creating an issue in the issue tracker is not a good way to get your answer, as it is monitored infrequently by a very small number of people.

When asking a question, it's helpful to provide as much of the following information as possible (people cannot help you if there's not enough information in your question):

  • the version (or the revision number if you check out from SVN directly) of Google Test you use (Google Test is under active development, so it's possible that your problem has been solved in a later version),
  • your operating system,
  • the name and version of your compiler,
  • the complete command line flags you give to your compiler,
  • the complete compiler error messages (if the question is about compilation),
  • the actual code (ideally, a minimal but complete program) that has the problem you encounter.

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理