【问题标题】:Testing with GTest and GMock: shared vs. static libraries使用 GTest 和 GMock 进行测试:共享库与静态库
【发布时间】:2014-02-09 19:40:47
【问题描述】:

我认为这个问题可能违反了网站的一些问答标准,因为我可能收到的答案可能被视为意见驱动的。不过,还是这样吧……

假设我们正在开发一个 C++ 项目,使用 CMake 来驱动构建/测试/打包过程,并使用 GTest 和 GMock 进行测试。进一步假设我们项目的结构是这样的:

cool_project
|
|-- source
| |
| |-- module_foo
| | |
| | |-- (bunch of source files)
| |
| |-- module_bar
| |
| |-- (yet more source files)
|
|-- tests
|
|-- module_foo
| |
| |-- (tests for module_foo)
|
|-- module_bar
|
|-- (tests for module_bar)

当然,这是一种过于简单化的情况,但你明白了。

现在,如果这些模块是库并且每个测试(即tests 下的每个目录)都是可执行文件,我们需要将后者与前者链接起来。问题是,如果这些库是共享的,加载器当然需要找到它们。一个明显的解决方案是将测试的工作目录设置为库的目录,使用 CMake 的set_property。但是,如果 GTest 和 GMock 也被构建为共享库,则这将不起作用,因为它们也需要加载。

我想出的解决方案是:

  • 将两个库(即 GTest 和 GMock)复制到模块的构建目录。这感觉有点愚蠢,因为共享库的主要好处(即在程序之间共享代码)被完全绕过,我们最终在构建目录中得到了几个副本。
  • 改为将 GTest 和 GMock 构建为静态库。这意味着我们现在最终将两个库的副本复制到每个可执行文件中,这增加了它的大小。尽管我们没有 1000 次测试,但这感觉有点尴尬。

因此,鉴于这种情况,我想知道是否有人对此感到震惊,以及他/她采取了什么道路。 (如果解决方案不是我提到的解决方案,我会很高兴听到有关它的所有信息。)理想情况下,我希望能够make && make test 并运行所有测试,而无需运行任何额外的脚本来适应事情。将所有库构建为静态库就可以了,但是如果我将它们构建为共享库呢?我必须建造两次吗?太傻了。

另一个问题也沿着这些思路运行,但我认为它的解决方案涉及重新设计或类似的工件。假设module_foo 依赖于第三方库,例如library_baz。如果module_foo 直接链接到library_baz,那么对前者的任何测试都需要加载library_baz,即使它可能正在测试不相关的功能。出现同样的问题。

Mocking 似乎是正确的做法,但不知何故,我觉得重构 module_foo 以使其与接口对话并没有多大意义(无论是通过动态多态还是静态多态)因为它不需要这种灵活性:library_baz 完成了这项工作。我想有些人会说“当然,你今天不需要灵活性,但谁知道明天呢?”。这对我来说似乎违反直觉,试图预览系统可能遇到的所有可能场景,但话又说回来,那里的人比我更有经验。

有什么想法吗?

【问题讨论】:

  • 您是否考虑将gtestgmock 安装为系统上的本地共享库,即在/usr/local/lib 中?如果您的 ldconfig 搜索路径正常,动态链接将在那里找到它们,然后您可以将 -lgtest -lgmock -pthread 添加到测试的链接选项中。是否有某些原因不适合您的测试设置?
  • 首先,很抱歉(非常)迟回复。此设置不能完美解决此问题的原因是,理想情况下,我希望将测试与应用程序一起部署,并且我不想强迫用户安装一些他们可能不知道的东西.

标签: c++ unit-testing architecture googletest gmock


【解决方案1】:

我认为这样做的方式(至少在 Windows 上,我不在 *nix 上开发)完全独立于任何测试:

只需将运行所需的所有二进制构建工件和依赖项复制(或直接在其中创建)到./bin 目录中。

然后您可以从这个./bin 目录执行任何可执行文件,并且所有共享库都在那里。

【讨论】:

  • 有道理,但我认为构建一个启用测试并遵循您的建议的项目将在 bin 目录中生成 大量 二进制文件,因为我使用 CTest 并且每个测试基本上都是一个可执行文件。无论如何感谢您的回答。
  • @faranwath - 请注意,我确实建议任何全局/bin 目录。只需..../my_project_dir/bin。这应该足够了,不是吗?
  • 当然,我只是想看看是否有人知道如何避免这样做,但我的希望完全基于个人而非实际问题。正如我所说,您的回答确实很有帮助。
  • @faranwath - 在一个目录中有许多测试可执行文件有什么问题?
  • 我不完全确定为什么我们一直在讨论这个问题,但我还是说:这绝对没有问题,事实上它可能是我未来选择的解决方案。我只是想要将每个测试可执行文件放在与其正在测试的模块关联的目录中。鉴于我是按照模块的结构来组织它们的,我大脑中喜欢对称的部分认为这将是一个好主意。
【解决方案2】:

看来我是想用核导弹杀死一只蚊子。

我想出的解决方案是简单地在测试时将所有库构建为静态对象。诚然,我最终得到了相当大的二进制文件,但我不会分发这些文件。

所以,总结一下:

  • GTest 和 GMock 都构建为静态库。
  • 包含我正在测试的功能的库也是如此。
  • 测试然后链接到那些,因此可以运行而不会弄乱工作目录。

此设置没有明显的缺点。每当我想尝试整个系统时,我都会切换到共享库。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多