6

我正在使用 CppUnit 设置一堆单元测试,但遇到的问题是没有一个测试正在运行。该项目分为几个小库,我计划以相同的方式划分单元测试类,然后将它们全部链接到一个单独的测试程序中。问题是,然后测试类在他们自己的库中,除非我明确调用它们,否则它们不会链接到主测试程序中,即我必须放入

runner.addTest( TestClass::suite() );

单独为每个测试类,不能使用 TestFactoryRegistry 的 makeTests() 方法来获取测试列表。如果我只是在顶层目录中将它们全部编译在一起,那么 makeTests() 方法可以正常工作,但如果我能提供帮助,我不想将所有测试类放在一个位置。

CppUnit 文档给出了以下小提示

使用 Helper 宏时的链接问题?

当您创建一个项目并编写它的单元测试套件时,通过使用所谓的帮助宏使工作变得更容易:CPPUNIT_TEST_SUITE_NAMED_REGISTRATION、CPPUNIT_REGISTRY_ADD 和 CPPUNIT_REGISTRY_ADD_TO_DEFAULT。问题是,如果您在 TestFixture 类的源代码文件中使用这些宏(例如 MyTest),并且如果您使用这样的一行

runner.addTest( CppUnit::TestFactoryRegistry::getRegistry().makeTest()

);

在 main.cpp 文件中的 main() 函数中,根本不会有测试运行!

原因很简单,如果您的 main.cpp 中没有未定义的符号,则链接阶段(构建过程的步骤之一)不要在最终的可执行文件中插入目标文件(.obj 或 .o 文件)。

这样,包含 AutoRegister 静态变量实例化的目标代码不是最终可执行文件的一部分,并且无法在 main() 函数中将自己插入到运行器中。

您必须在 main.cpp 中创建一个未定义的符号,以便 mytest.o 文件与 main.o 集成到最终的可执行文件中。

米歇尔·诺拉德犯下的诡计

但没有说如何使这项工作,我只是足够密集,无法自己弄清楚或在网上找到一个例子。

现在我可以为每个库单独做一个可执行的测试,最后我可能会这样做,但我想先让它工作,所以我只需要运行一个测试程序来测试整个事情。有关如何使其发挥作用的任何想法/示例?

4

3 回答 3

1

通过向 main 添加一个未定义的符号,他只是意味着创建任何随机外部符号来强制链接器搜索包含测试代码的外部库。

例如,假设有两个测试库 fred 和 barney,在 fredTestLib.cpp 中您只需添加以下行:

int fredDummyInt = 0; // declare a unique symbol for the linker to resolve

在 barneyTestLib.cpp 中,您将添加类似的行:

int barneyDummyInt = 0; // a different unique symbol for the linker to resolve

您可以在不同的步骤中分别编译每个库。然后在主测试程序中强制链接器解析它们。因此,将这些行添加到 main.cpp:

extern int fredDummyInt;
extern int barneyDummyInt;
...
main () {
    ...
    fredDummyInt++; // give the linker some symbols to resolve
    barneyDummyInt++;
    ...

这个想法(根据上述技巧的作者所说)是因为链接器已经在 fredTest.lib 中搜索 fredDummyInt,它也会找到并解决您自动注册的测试。

注意:我没有尝试过这个,看看它是否有效!我只是在回答你关于外部的问题。

要考虑的另一种方法是在 DLL 中创建测试,并使用 LoadLibrary() 显式地将它们带入运行。对于矫枉过正,如果您使用 MfcUi::TestRunner,您可能会构建一个小的下拉 GUI 东西,让您选择要加载的库,加载它,然后显示要在该库中运行的测试,然后运行它们。

于 2009-06-24T14:36:40.967 回答
0

我意识到这篇文章现在已经很老了,但是对于遇到它的其他人来说:在代码中没有引用的情况下解决这个问题的一种方法是指示(强制)链接器将整个静态库包含在二进制文件中。详细信息区域可从 gcc 和 ld 手册页获得,这篇文章也涵盖了它: How to force gcc to link unreferenced, static C++ objects from a library

根据 ld 的手册页,考虑明确关闭该选项很重要(也显示在上面的示例之一中)。

于 2013-01-15T21:46:44.687 回答
0

这个问题的解决方案就像之前所说的那样简单(但可能不是很优雅)。对于位于外部库中的每个 TestFixture,您必须在主模块中添加以下两行代码

#include <CppUnitTestFixtureExample.h>
CppUnitTestFixtureExample Test1;

它创建了一个未使用的虚拟变量,它只是强制链接器链接测试夹具。现在位于主模块中的测试运行器能够运行测试。

于 2012-01-25T14:09:49.980 回答