使用CppUnit链接测试库

时间:2023-01-13 10:21:52

I'm setting up a bunch of unit tests using CppUnit but am having the problem that none of the tests are being run. The project is divided up into several small libraries and I planned on dividing the unit test classes up the same way and then linking them all into a single test program. The problem is, then the test classes are in their own libraries, they don't get linked into the main test program unless I explicitly call them, i.e. I have to put in

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

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

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

individually for each test class and can't use the TestFactoryRegistry's makeTests() method to get the list of tests. If I just compile them all together in the top directory the makeTests() method works fine but I don't want to have all the test classes in one location if I can help it.

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

The CppUnit documentation gives the following little hint

CppUnit文档提供了以下一点提示

Linking problem when using Helper macros ?

使用Helper宏时链接问题?

When you create a project and write its unit test suites, the work is made easier through the use of the so-called helper macros : CPPUNIT_TEST_SUITE_NAMED_REGISTRATION, CPPUNIT_REGISTRY_ADD and CPPUNIT_REGISTRY_ADD_TO_DEFAULT. The problem is that if you use those macros in the source code file of a TestFixture class (say MyTest as an example), and if you use a line like this one

当您创建项目并编写其单元测试套件时,通过使用所谓的帮助程序宏可以更轻松地完成工作:CPPUNIT_TEST_SUITE_NAMED_REGISTRATION,CPPUNIT_REGISTRY_ADD和CPPUNIT_REGISTRY_ADD_TO_DEFAULT。问题是,如果你在TestFixture类的源代码文件中使用这些宏(比如说MyTest作为例子),如果你使用像这样的一行

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

);

in your main() function in file main.cpp, there will have no test run at all !

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

The reason is simply that the link stage, one of the step of the build process, do not insert the object files (.obj or .o files) in the final executable if there is no undefined symbol in your main.cpp.

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

That way, the object code which contains the AutoRegister static variables instantiation is not part of the final executable and is not able to insert oneself into the runner in the main() function.

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

You have to create an undefined symbol in main.cpp so that the mytest.o file is integrated with main.o into the final executable.

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

Trick committed by Michel Nolard

Michel Nolard犯下的伎俩

but doesn't say how to make this work and I'm just dense enough not to be able to figure it out myself or find an example on-line.

但并没有说如何使这项工作,我只是足够密集,不能自己弄明白或在网上找到一个例子。

Now I could just make a separate executable test for each library, and in the end I may go that way, but I wanted to try to get this working first so I just had one single test program to run to test the whole thing. Any ideas/examples of how to get this to work?

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

3 个解决方案

#1


1  

By adding an undefined symbol to main, he just means create any random external symbol to force the linker into searching your external libraries that contain the test code.

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

For example, assuming two test libraries fred and barney, in fredTestLib.cpp you'd just add this line:

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

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

and in barneyTestLib.cpp, you'd add a similar line:

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

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

You could compile each library separately in different steps. In the main test program, you then force the linker to resolve them. So add these lines to main.cpp:

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

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

The idea (according to what the author of the trick above is saying) is that because the linker is already searching fredTest.lib for fredDummyInt, it will also find and resolve your automatically registered tests.

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

Note: I have not tried this to see if it works! I'm just answering your question about externals.

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

Another approach to consider would be to create your tests in DLLs, and use LoadLibrary() to explicitly bring them in to run. For overkill, if you use the MfcUi::TestRunner, you could probably build a little drop-down GUI thing that lets you pick the library to load, loads it, then displays the tests to run in that library, then runs them.

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

#2


0  

The solution for this problem is rather simple as statet before (but may not be very elegant). For each TestFixture that is located in an external library you have to add the following two lines of code in the main module

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

#include <CppUnitTestFixtureExample.h>
CppUnitTestFixtureExample Test1;

It creates an unused dummy variable that is not used, it just forces the linker to link the test fixture. Now the test runner that is located in the main module is able to run the test.

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

#3


0  

I realize this post is now quite old, but for anyone else who comes across it: One way to address this w/out having references in your code is to instruct (force) the linker to include the entire static library in the binary. Details area available from the gcc & ld man pages, and this post covers it too: How to force gcc to link unreferenced, static C++ objects from a library

我意识到这篇文章现在已经很老了,但对于遇到它的其他人来说:解决这个问题的一种方法是在代码中引用它是指示(强制)链接器将整个静态库包含在二进制文件中。详细信息区域可以从gcc和ld手册页获得,这篇文章也包括它:如何强制gcc链接来自库的未引用的静态C ++对象

Per ld's man page, it's important to consider explicitly turning the option off (also shown in one of the examples above).

在每个人的手册页中,重要的是要考虑明确关闭选项(也在上面的一个例子中显示)。

#1


1  

By adding an undefined symbol to main, he just means create any random external symbol to force the linker into searching your external libraries that contain the test code.

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

For example, assuming two test libraries fred and barney, in fredTestLib.cpp you'd just add this line:

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

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

and in barneyTestLib.cpp, you'd add a similar line:

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

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

You could compile each library separately in different steps. In the main test program, you then force the linker to resolve them. So add these lines to main.cpp:

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

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

The idea (according to what the author of the trick above is saying) is that because the linker is already searching fredTest.lib for fredDummyInt, it will also find and resolve your automatically registered tests.

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

Note: I have not tried this to see if it works! I'm just answering your question about externals.

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

Another approach to consider would be to create your tests in DLLs, and use LoadLibrary() to explicitly bring them in to run. For overkill, if you use the MfcUi::TestRunner, you could probably build a little drop-down GUI thing that lets you pick the library to load, loads it, then displays the tests to run in that library, then runs them.

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

#2


0  

The solution for this problem is rather simple as statet before (but may not be very elegant). For each TestFixture that is located in an external library you have to add the following two lines of code in the main module

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

#include <CppUnitTestFixtureExample.h>
CppUnitTestFixtureExample Test1;

It creates an unused dummy variable that is not used, it just forces the linker to link the test fixture. Now the test runner that is located in the main module is able to run the test.

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

#3


0  

I realize this post is now quite old, but for anyone else who comes across it: One way to address this w/out having references in your code is to instruct (force) the linker to include the entire static library in the binary. Details area available from the gcc & ld man pages, and this post covers it too: How to force gcc to link unreferenced, static C++ objects from a library

我意识到这篇文章现在已经很老了,但对于遇到它的其他人来说:解决这个问题的一种方法是在代码中引用它是指示(强制)链接器将整个静态库包含在二进制文件中。详细信息区域可以从gcc和ld手册页获得,这篇文章也包括它:如何强制gcc链接来自库的未引用的静态C ++对象

Per ld's man page, it's important to consider explicitly turning the option off (also shown in one of the examples above).

在每个人的手册页中,重要的是要考虑明确关闭选项(也在上面的一个例子中显示)。