2

我正在尝试使用谷歌测试为我的 Qt(c++) 应用程序编写一个测试套件,主要问题是我的应用程序由一个主程序和各种共享库组成。一切工作正常,直到我尝试使用 gcov/lcov(它不能在动态库上运行)进行一些代码覆盖,所以我修改了所有 .pro 文件以使用以下方法进行静态库编译:


CONFIG += staticlib create_prl
QMAKE_LFLAGS += -static
LIBS += ../../Libs/lib*.a

问题是谷歌测试测试应用程序是这样的:



int main(int argc, char **argv) {

  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

所以它在运行时检测到链接,这意味着当我在这里编译测试应用程序时没有警告或任何表明问题的东西,并且在运行测试应用程序时它执行 0 test 因为它没有找到任何东西。

我的解决方案(摆脱烦人的)是在每个类中定义将用于测试虚假公共静态成员并对其进行主要测试应用程序的操作:


class SETTINGS_TESTS_SHARED_EXPORT SettingsTests: public testing::Test {

public:
 SettingsTests();
 virtual ~SettingsTests();

 static bool dummy;
protected:
 virtual void SetUp();
 virtual void TearDown();

private:
 Settings* _setting0;
 Settings* _setting1;
 Settings* _setting2;
};



using namespace MBI::SETTINGS;
using namespace MBI::TESTS;

int main(int argc, char **argv) {

  SettingsTests::dummy = true;
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

所以我可以在我的应用程序上强制链接该库。

我还发现选项 -u 可以在 gcc 中执行类似的操作,但似乎不起作用。如果在编译时没有检测到符号,有没有人有办法强制静态库链接?

4

2 回答 2

0

在 google 测试文档中提到了与 Visual c++ dll 的链接问题:

Visual C++ 用户的重要说明

如果您将测试放入库中并且您的 main() 函数位于不同的库或 .exe 文件中,则这些测试将不会运行。原因是 Visual C++ 中的一个错误。当您定义测试时,Google Test 会创建某些静态对象来注册它们。这些对象没有从其他地方引用,但它们的构造函数仍然应该运行。当 Visual C++ 链接器发现库中的任何内容都没有从其他地方引用时,它会将库抛出。您必须使用主程序中的测试来引用您的库,以防止链接器丢弃它。这是如何做到的。在您的库代码中的某处声明一个函数:

__declspec(dllimport) int PullInMyLibrary() { return 0; }
如果您将测试放在静态库(而不是 DLL)中,则不需要 __declspec(dllexport)。现在,在您的主程序中,编写一个调用该函数的代码:

int PullInMyLibrary();
静态 int 虚拟 = PullInMyLibrary();
这将使您的测试保持引用,并使它们在启动时注册自己。

此外,如果您在静态库中定义测试,请将 /OPT:NOREF 添加到主程序链接器选项中。如果您使用 MSVC++ IDE,请转到您的 .exe 项目属性/配置属性/链接器/优化并将引用设置设置为保留未引用的数据 (/OPT:NOREF)。这将防止 Visual C++ 链接器从最终可执行文件中丢弃测试生成的单个符号。

不过,还有一个陷阱。如果您将 Google Test 用作静态库(这就是它在 gtest.vcproj 中的定义方式),您的测试也必须驻留在静态库中。如果您必须将它们放在 DLL 中,则必须将 Google Test 也更改为构建到 DLL 中。否则,您的测试将无法正确运行或根本不会运行。这里的一般结论是:让您的生活更轻松 - 不要在库中编写测试!

采用的解决方案几乎就是我用 g++ 所做的。我怀疑 qmake 产生中间文件 moc_* 并且我的代码与之相关联的事实。

于 2009-11-24T08:00:42.247 回答
0

我不完全理解这个问题,它没有解释什么::testing::InitGoogleTestRUN_ALL_TESTS实际做什么,以及它们与动态链接的关系。

但是:您可以通过使用选项使 GNU 链接器在链接时忽略未解析的符号--unresolved-symbols=ignore-all,或者如果您需要将选项传递给 gcc -Wl,--unresolved-symbols=ignore-all,.

于 2009-11-23T22:46:10.470 回答