【问题标题】:Redefined Catch unit tests重新定义 Catch 单元测试
【发布时间】:2017-11-21 17:36:28
【问题描述】:

我正在测试一个巨大的软件,并希望使用 Catch 来完成这项任务。 我正在使用“单一包含”版本 1.9,将其集成到 Visual Studio 2012 更新 4 中并使用 C++04 标准。

如下所示,我使用了三个“.cpp”文件。他们每个人都参考:

  • 提供“抽象”宏的包含文件(例如#define Assert(x) REQUIRE(x));
  • 一个实用文件,为测试提供...实用程序;
  • 具体的测试目标包含文件;
  • 一些“使用命名空间”语句,所有 cpp 文件“使用”同一个命名空间;
  • 使用宏编写的实际测试(例如Assert(2 == getNumber()))。

有关以下文件内容的更多详细信息。

此配置有效,但其中一个测试文件日益变大,我想将其分成 3 个或更多。现在,假设我执行以下操作:

  • 获取测试test.cpp的部分内容并将其移动到新文件test2.cpp
  • 添加相同的包含和定义以使其编译;
  • 在我的 main 中包含新文件

运行测试时会弹出此错误:

=============================
No tests ran
error: TEST_CASE( "test 2" ) already defined.
    First seen at c:\tests\catchtest2\catchtest2\test2.cpp(3)
    Redefined at c:\tests\catchtest2\catchtest2\test2.cpp(3)

其中test2.cpp 是新文件。 如果我将内容移回test.cpp,一切正常,但是处理数千行长的测试几乎比处理项目本身更难,而且维度可能会增长 3 倍、4 倍。 有没有办法将测试拆分为多个文件?

-- 注释--

我认为在标头中包含 Catch 并直接使用包含标头而不是 catch.cpp 不是一个好主意,但我成功地使用此配置与 3 个(正好 3 个)包含 .cpp 测试文件,我无法将其与 4 个文件一起使用。

我记得读过它与定义组件的 有某种关系,但我也可以移动代码,以便在不同的行定义测试用例并且行为不会不改变。

我也尝试过“清理和重建”,因为很可能脏数据保存在编译器/链接器的缓存中,但无济于事。

我现在无法创建实际的 MWE,因此我为您提供了一个测试设置的草图,该草图与我认为可能需要的一样准确。我非常愿意提供更多详细信息或尝试构建一个实际的 MWE 并分享它。

任何想法都值得赞赏!


我的“工作”代码如下所示:

ma​​in.cpp

#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include "test1.cpp"
#include "test2.cpp"
#include "test3.cpp"

int main( int argc, char* argv[] )
{
    cleanDir("c:\\temp");
    init (argv);
    int result = Catch::Session().run( argc, argv );
    return ( result < 0xff ? result : 0xff );
}

test1.cpp

#include "unitTestSuite.h"
#include "utils.h"
#include "systemundertest.h"

using namespace system::under::test;

my_test_case("test 1") {
    my_section("does X") {
        // tests...
    }
}

my_test_case("test 2") {
    my_section("does Y") {
        // tests...
    }
}

unitTestSuite.h

#ifndef UNIT_TEST_SUITE
#define UNIT_TEST_SUITE 1

#include "catch.hpp"
#define my_test_case(x) TEST_CASE("Testing: " x)
... // here is also a namespace with some unit test specific utils
#endif

utils.h

#ifndef _UTILS_
#define _UTILS_
// some global variables declared here and defined in utils.cpp
// template functions defined in the header
// non-template functions defined in utils.cpp
// a test generation namespace with some template functions and some non-template functions defined in utils.cpp
#endif

“分裂”之后:

test1.cpp

#include "unitTestSuite.h"
#include "utils.h"
#include "systemundertest.h"

using namespace system::under::test;

my_test_case("test 1") {
    my_section("does X") {
        // tests...
    }
}

test1.2.cpp

#include "unitTestSuite.h"
#include "utils.h"
#include "systemundertest.h"

using namespace system::under::test;

my_test_case("test 2") {
    my_section("does Y") {
        // tests...
    }
}

ma​​in.cpp

#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include "test1.cpp"
#include "test1.2.cpp"
#include "test2.cpp"
#include "test3.cpp"

int main( int argc, char* argv[] )
{
    cleanDir("c:\\temp");
    init (argv);
    int result = Catch::Session().run( argc, argv );
    return ( result < 0xff ? result : 0xff );
}

程序输出:

=============================
No tests ran
error: TEST_CASE( "test 2" ) already defined.
    First seen at c:\tests\catchtest2\catchtest2\test1.2.cpp(3)
    Redefined at c:\tests\catchtest2\catchtest2\test1.2.cpp(3)

【问题讨论】:

  • 为什么要包含 cpp 文件?
  • 这似乎是 catch 管理测试的方式。我尝试在单独的 cpp 文件中包含标头和定义测试,但是运行了 8 个断言而不是 1750,所以我想出了点问题^^"
  • 我认为你的 main.cpp 只需要前两行。您可以将测试 cpp 中的目标文件链接到与使用 main.cpp 构建的相同的可执行文件中。根据经验,如果你包含一个 cpp 文件,你会做一些奇怪的事情。
  • 嗯,所有 catch 示例都使用这种模式,所以我认为“catch magic”必须发生。我将尝试删除 cpp 引用并返回此线程,谢谢您的建议 :)
  • 你有例子的参考吗?如果需要的话,我很高兴接受再教育。

标签: c++ visual-studio-2012 catch-unit-test


【解决方案1】:

不要包含 cpp 文件,只需将它们添加到项目中即可。 您的 main.cpp 文件只需要前两行(定义和包含)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-15
    • 1970-01-01
    • 2010-10-08
    • 2011-11-05
    • 2020-06-08
    • 1970-01-01
    • 2018-02-25
    • 2015-01-11
    相关资源
    最近更新 更多