C++ Boost 测试、包结构和 Eclipse 项目设置

C++ Boost Test, package structure, and Eclipse project settings

我使用的是 C++98,除了标准库之外,我只能访问旧版本的 Boost(幸好有 Boost Test)。文档虽然令人生畏、冗长,但我不知道从哪里开始。

我有一些在 Java 中进行单元测试的经验(并且我正在寻找 C++ 中的单元测试),并且我已经看到 test 包含独立于src 包,我还看到了 Where do you put your unit test? as well as Unit Testing with Boost and Eclipse。他们的建议各不相同,并提出了将测试代码与生产代码分开或放在一起的不同打包结构的推理。

在我开始研究 Boost 测试之前,我在 Eclipse 中创建了这个结构(可能是错误的):

-- ProjectName
   |-- Debug
   |-- src
   |-- test

我写了另一个 main 方法来 运行 测试函数。 Eclipse 不喜欢这样,因为我在同一个项目中有两个主要方法。我在 Project Properties 中摸索着,没有发现任何有用的东西可以在构建(链接,真的)时将我的生产代码与测试代码分开。我的临时修复是在终端中使用 g++ 并临时编译我的 "test" 代码。

我在 Boost::Test -- generation of Main()? 上发现了一些暗示,Boost 实际上生成了它自己的 main 方法,所以这是我目前的单元测试攻击计划,特别是对于已经可用的测试工具库。

  • What is the conventional way of organizing unit tests for C++?
  • How do I get started with Boost Test? (Boost is already installed)
  • Is there anything I need to change in Eclipse to be able to run my Boost unit tests separate from my production code within the IDE? (One of the nice things about IntelliJ, with Java, is how it'll automatically run any main method you like with a click) -- The goal here to be able to build and run my tests within Eclipse.
  • Should my tests be in a separate Eclipse project? (this was suggested in an answer to the second SO question I linked)

编辑:我发现 this 文章介绍了 Boost 测试,但它没有讨论如何在 IDE 中处理它设置。

我自己想出了如何做到这一点,我会为其他刚开始使用 C++ 并需要测试他们的代码的人记录我的解决方案。目前我找不到任何好的介绍。以下是我使用过的(并且发现有用的)资源:

  • C++ Unit Testing With Boost Test 以比 Boost 文档更好的方式介绍了 Boost 测试。
  • Where do you put your unit test? 讨论了使用 C++ 进行测试的最传统方法。
  • unit test in eclipse g++ 讨论了允许测试的 Eclipse 构建配置

C++ 的测试约定与其他编码语言的约定类似,只需将测试写在项目下名为 test 的目录中即可。使用 Boost Test 需要您 link 单元测试框架:-l boost_unit_test_framework 在 Eclipse 中:

Right click on your project, go to Properties, C/C++ Build, Settings, Tool Settings, GCC C++ Linker, Libraries, and add the library name boost_unit_test_framework (add -mt to the name if you require multithreading; additionally, once the testing build configuration exists, you can go back and choose just that configuration to link the library -- it'll reduce the size of your executable for your other builds).

为了能够 运行 Eclipse 中的单元测试与您的主要方法分开,我们需要建立一个新的构建配置。这样,Eclipse 就知道在执行测试时使用 main 方法排除源文件。

Click on Project, Build Configurations, Manage..., and select New... and call it Test (or something other than test). Choose your existing configuration so that we'll inherit properties from the production build.

接下来,我们需要区分构建配置,以便在构建它们时,它们实际上对应于生产和测试构建。

Right click on test, Resource Configurations, Exclude from Build..., and select the builds that represent your production build (i.e. Debug and or Release). Once done with that, right click on your source file with your main method, and exclude that from the Test build.

我们还有一些地方需要改变。我们还没有任何测试代码,但我们仍然无法 运行 我们的测试构建,我们的测试构建也不会知道 src 中存在的资源,因为 Eclipse 不会自动包含这些源文件. test.

中的测试代码几乎看不到它们

Right click on your project, go to Properties, C/C++ Build, Settings, Tool Settings, GCC C++ Compiler, Includes, and add the path /.../workspace/ProjectName.

现在为了能够 运行 在 Eclipse 中构建您的测试,它需要知道您期望 IDE 到 运行 的可执行文件。

Click on Run, Run Configurations..., and looking at your current run configuration, consolidate these settings by giving, for example, a debug build the name "Debug Build", the C/C++ Application "Debug/Artifact_Name", and the Build Configuration "Debug". Next, create a new run configuration, and call it something like "Test Build", set C/C++ Application to "Test/Artifact_Name", and ensure the build configuration is Test.

现在您可以通过选择 "active" 构建配置或 运行ning 正确的 运行 在 运行ning 生产代码和测试代码之间切换配置。

最后,这是一个使用 Boost Test 进行单元测试的示例,一旦所有这些都设置好了:

//unit_tests.cpp
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE someModuleName
#include <boost/test/unit_test.hpp>
#include <src/some_object.h>

struct template_objects {
    some_object x;
    template_objects() {
        BOOST_TEST_MESSAGE("Setting up testing objects");
    }
    ~template_objects() {
        BOOST_TEST_MESSAGE("Tearing down testing objects");
    }
}

BOOST_FIXTURE_TEST_SUITE(testSuiteName, template_objects)

BOOST_AUTO_TEST_CASE(testCase1) {
    x.update();
    BOOST_CHECK(x.is_up_to_date());
}
BOOST_AUTO_TEST_CASE(testCase2) {
    BOOST_CHECK(x.is_not_up_to_date());
}

BOOST_AUTO_TEST_SUITE_END()

这演示了使用提升测试的一些重要事项:

  • 建议定义BOOST_TEST_DYN_LINK;在包含任何 Boost 库
  • 之前,您需要定义一种 link 测试框架的方法
  • 你必须给 "module" 命名,不必是文件名
  • 为了在进入测试用例之前自动设置和拆卸对象,Boost Test 具有 fixtures,它允许您多次调用对象的预先存在的状态
  • struct 将这些装置分组,这意味着您的对象应该有一个定义良好的构造函数和析构函数来自动确定范围(如果您没有调用 new,您就不会拆解时不需要 delete)
  • 测试套件只是对测试用例进行逻辑分组的一种方式(我还没有测试过,但您可以将套件分成多个文件以实现更好的逻辑分离)

其他花絮:要使 Boost 测试更详细,请转到测试构建的 运行 配置,并添加参数 --log_level=test_suite.