【问题标题】:CATCH Unit Testing Suite with Visual Studio 2010带有 Visual Studio 2010 的 CATCH 单元测试套件
【发布时间】:2013-08-02 04:16:13
【问题描述】:

据我了解,我可以简单地将catch.hpp 放入我的项目目录,将其添加到项目中,然后开始编写测试。一旦我尝试使用tutorial 中列出的一些宏,我就会遇到几个,或者准确地说是 11 个链接器错误。

#include "catch.hpp"

unsigned int Factorial( unsigned int number ) {
    return number <= 1 ? number : Factorial(number-1)*number;
}

TEST_CASE( "Factorials are computed", "[factorial]" ) {
    REQUIRE( Factorial(1) == 1 );
    REQUIRE( Factorial(2) == 2 );
    REQUIRE( Factorial(3) == 6 );
    REQUIRE( Factorial(10) == 3628800 );
}

我可以从第一个示例中创建一个文件并使用 g++ 编译它,但是当我将相同的代码粘贴到我的 VS2010 项目中然后尝试运行它时,我遇到了链接器错误。不幸的是,此时我对 C++ 还不够熟悉,无法自己解码错误,在查看了单个文件 here 后,我无法辨别问题。

Error   1   error LNK2019: unresolved external symbol "public: __thiscall Catch::AutoReg::AutoReg(void (__cdecl*)(void),struct Catch::SourceLineInfo const &,struct Catch::NameAndDesc const &)" (??0AutoReg@Catch@@QAE@P6AXXZABUSourceLineInfo@1@ABUNameAndDesc@1@@Z) referenced in function "void __cdecl `anonymous namespace'::`dynamic initializer for 'autoRegistrar27''(void)" (??__EautoRegistrar27@?A0x3911e331@@YAXXZ)    C:\Users\Mark\documents\visual studio 2010\Projects\FirstCPPApplication\FirstCPPApplication\FirstCPPApplication.obj 1   1   FirstCPPApplication
Error   2   error LNK2019: unresolved external symbol "public: __thiscall Catch::ExpressionResultBuilder::ExpressionResultBuilder(enum Catch::ResultWas::OfType)" (??0ExpressionResultBuilder@Catch@@QAE@W4OfType@ResultWas@1@@Z) referenced in function __catch$?____C_A_T_C_H____T_E_S_T____27@@YAXXZ$0   C:\Users\Mark\documents\visual studio 2010\Projects\FirstCPPApplication\FirstCPPApplication\FirstCPPApplication.obj 1   1   FirstCPPApplication
Error   3   error LNK2019: unresolved external symbol "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Catch::translateActiveException(void)" (?translateActiveException@Catch@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ) referenced in function __catch$?____C_A_T_C_H____T_E_S_T____27@@YAXXZ$0   C:\Users\Mark\documents\visual studio 2010\Projects\FirstCPPApplication\FirstCPPApplication\FirstCPPApplication.obj 1   1   FirstCPPApplication
Error   4   error LNK2019: unresolved external symbol "public: class Catch::ExpressionResultBuilder & __thiscall Catch::ExpressionResultBuilder::endExpression(enum Catch::ResultDisposition::Flags)" (?endExpression@ExpressionResultBuilder@Catch@@QAEAAV12@W4Flags@ResultDisposition@2@@Z) referenced in function "void __cdecl ____C_A_T_C_H____T_E_S_T____27(void)" (?____C_A_T_C_H____T_E_S_T____27@@YAXXZ)   C:\Users\Mark\documents\visual studio 2010\Projects\FirstCPPApplication\FirstCPPApplication\FirstCPPApplication.obj 1   1   FirstCPPApplication
Error   5   error LNK2019: unresolved external symbol "public: __thiscall Catch::AssertionInfo::AssertionInfo(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,struct Catch::SourceLineInfo const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,enum Catch::ResultDisposition::Flags)" (??0AssertionInfo@Catch@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABUSourceLineInfo@1@0W4Flags@ResultDisposition@1@@Z) referenced in function "void __cdecl ____C_A_T_C_H____T_E_S_T____27(void)" (?____C_A_T_C_H____T_E_S_T____27@@YAXXZ) C:\Users\Mark\documents\visual studio 2010\Projects\FirstCPPApplication\FirstCPPApplication\FirstCPPApplication.obj 1   1   FirstCPPApplication
Error   6   error LNK2019: unresolved external symbol "struct Catch::IContext & __cdecl Catch::getCurrentContext(void)" (?getCurrentContext@Catch@@YAAAUIContext@1@XZ) referenced in function "struct Catch::IResultCapture & __cdecl Catch::getResultCapture(void)" (?getResultCapture@Catch@@YAAAUIResultCapture@1@XZ)    C:\Users\Mark\documents\visual studio 2010\Projects\FirstCPPApplication\FirstCPPApplication\FirstCPPApplication.obj 1   1   FirstCPPApplication
Error   7   error LNK2019: unresolved external symbol "public: class Catch::ExpressionResultBuilder & __thiscall Catch::ExpressionResultBuilder::setOp(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?setOp@ExpressionResultBuilder@Catch@@QAEAAV12@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "private: class Catch::ExpressionResultBuilder & __thiscall Catch::ExpressionLhs<int const &>::captureExpression<0,int>(int const &)" (??$captureExpression@$0A@H@?$ExpressionLhs@ABH@Catch@@AAEAAVExpressionResultBuilder@1@ABH@Z) C:\Users\Mark\documents\visual studio 2010\Projects\FirstCPPApplication\FirstCPPApplication\FirstCPPApplication.obj 1   1   FirstCPPApplication
Error   8   error LNK2019: unresolved external symbol "public: class Catch::ExpressionResultBuilder & __thiscall Catch::ExpressionResultBuilder::setRhs(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?setRhs@ExpressionResultBuilder@Catch@@QAEAAV12@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "private: class Catch::ExpressionResultBuilder & __thiscall Catch::ExpressionLhs<int const &>::captureExpression<0,int>(int const &)" (??$captureExpression@$0A@H@?$ExpressionLhs@ABH@Catch@@AAEAAVExpressionResultBuilder@1@ABH@Z)   C:\Users\Mark\documents\visual studio 2010\Projects\FirstCPPApplication\FirstCPPApplication\FirstCPPApplication.obj 1   1   FirstCPPApplication
Error   9   error LNK2019: unresolved external symbol "public: class Catch::ExpressionResultBuilder & __thiscall Catch::ExpressionResultBuilder::setLhs(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?setLhs@ExpressionResultBuilder@Catch@@QAEAAV12@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "private: class Catch::ExpressionResultBuilder & __thiscall Catch::ExpressionLhs<int const &>::captureExpression<0,int>(int const &)" (??$captureExpression@$0A@H@?$ExpressionLhs@ABH@Catch@@AAEAAVExpressionResultBuilder@1@ABH@Z)   C:\Users\Mark\documents\visual studio 2010\Projects\FirstCPPApplication\FirstCPPApplication\FirstCPPApplication.obj 1   1   FirstCPPApplication
Error   10  error LNK2019: unresolved external symbol "public: class Catch::ExpressionResultBuilder & __thiscall Catch::ExpressionResultBuilder::setResultType(bool)" (?setResultType@ExpressionResultBuilder@Catch@@QAEAAV12@_N@Z) referenced in function "private: class Catch::ExpressionResultBuilder & __thiscall Catch::ExpressionLhs<int const &>::captureExpression<0,int>(int const &)" (??$captureExpression@$0A@H@?$ExpressionLhs@ABH@Catch@@AAEAAVExpressionResultBuilder@1@ABH@Z)  C:\Users\Mark\documents\visual studio 2010\Projects\FirstCPPApplication\FirstCPPApplication\FirstCPPApplication.obj 1   1   FirstCPPApplication
Error   11  error LNK2019: unresolved external symbol "public: __thiscall Catch::AutoReg::~AutoReg(void)" (??1AutoReg@Catch@@QAE@XZ) referenced in function "void __cdecl `anonymous namespace'::`dynamic atexit destructor for 'autoRegistrar27''(void)" (??__FautoRegistrar27@?A0x3911e331@@YAXXZ)    C:\Users\Mark\documents\visual studio 2010\Projects\FirstCPPApplication\FirstCPPApplication\FirstCPPApplication.obj 1   1   FirstCPPApplication
Error   12  error LNK1120: 11 unresolved externals  C:\Users\Mark\documents\visual studio 2010\Projects\FirstCPPApplication\Debug\FirstCPPApplication.exe   FirstCPPApplication

【问题讨论】:

    标签: c++ unit-testing


    【解决方案1】:

    长话短说:将您的单个项目解决方案拆分为 3 个,使用旧的 exe.lib,将项目添加到适当的路径,更新链接器,一切顺利。

    AE Drew's answer 帮助解决了我的问题,但我想放一个更完整的 问题标题的解决方案,以防有人来自谷歌, 特别是如果他们正在寻找初学者的简单故障 观点。

    如果您的解决方案中只有一个项目为您构建了 .exe,那么 CATCH 行不通:您的解决方案需要 3 个项目(据我所知)才能 测试你的代码。

    • Source_project,主要代码库项目(其中源代码为 您的应用程序驻留)

    • Test_project,测试套件项目(REQUIRES 测试出现在其中 如上述问题所述)

    • Main_project,您实际调用并运行代码的项目 源代码库。

    为了将您原来的单一项目解决方案转换为 您可以在两个测试中使用并正确运行,您需要构建一个 .lib 或 一个.dll,以便其他项目(包括其他人的项目)可以使用 相同的代码。更改this answer,只需

    在解决方案资源管理器中右键单击您的项目,然后选择 > 属性.... 在配置属性 -> 常规下有一个 > 选项 称为配置类型。如果您将其更改为 [静态库 > (.lib)],您的 项目在构建时会生成一个 [.lib]。

    然后在第三个项目main_project 中,您有一个准系统设置 从只包含一个看起来像东西的文件的 Win32 控制台应用程序 喜欢:

    #include "stdafx.h"
    #include "HEADER_FROM_FIRST_PROJECT.h"
    
    int _tmain(int argc, _TCHAR* argv[])
    {
       METHOD_FROM_FIRST_PROJECT();
       return 0;
    }
    

    您从Source_project 导入头文件,这是我们的第一个项目 已创建(以前是 exe,但现在正在构建为 lib)。但 这还不会运行,您需要将Source_project 的目录添加到 这个项目的附加目录,通过右键单击项目中的 解决方案资源管理器,在属性 > 配置属性 > C/C++ > 常规 > 附加包含目录,将source_project 的文件夹添加到列表中。这会 允许#include 行自动在该目录中搜索适当的 文件,让你不必写../source_project/HEADER_FROM_FIRST_PROJECT.h

    最后,最后一步是确保链接器能够实际 找到您要包含的对象。因为我们正在建立一个 .lib,我们可以很简单地做到这一点。在相同的设置对话框中 之前,项目属性对话框,我们将导航到配置 Properties > Linker > Input > Additional Dependencies 并将相对路径添加到 source_project.lib 文件,类似于 ../Debug/source_project.lib

    请注意,如果您在旧的 exe 项目中有任何 .dlls,它将 需要移动到新的main_project

    另外请注意,这对我来说都是全新的,有些条款和信息肯定是不正确的。

    【讨论】:

    • 非常感谢您的详细解释。对像我这样的 C++ 新手帮助很大。
    【解决方案2】:

    只需浏览您提供的链接,我认为您可能需要在文件顶部添加这一行。

    #define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
    

    您尝试链接的函数似乎在 #if defined CATCH_CONFIG_MAIN .... #endif 预处理器指令中。

    【讨论】:

    • 谢谢,这就是解决方案。在我没有经验的情况下,我假设我不需要一个新项目来编写我的单元测试,所以我错误地假设我可以将catch.hpp 放置在我的项目中的任何位置,所以通过创建一个新项目并添加行OP和你的单行它有效。现在我需要梳理一下如何将我要测试的代码从主项目添加到测试项目中。
    • 从头开始,我在主项目中有一个导入的相对路径,但在测试项目中会失败,因为我为每个项目使用了不同的项目设置。我想我没有链接到正确的文件或其他东西。
    猜你喜欢
    • 2012-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多