Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CATCH Unit Testing Suite with Visual Studio 2010

As far as I understand it, I can simply place catch.hpp into my project directory, add it to the project, and then start writing tests. I'm running into a few, or 11 to be exact, linker errors once I try using some of the macros outlined in the tutorial.

#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 );
}

I'm able to create a single file out of the first example and compile it with g++, but when I just paste the same code into my VS2010 project and then try to run it, I run into the linker errors. Unfortunately I'm not familiar enough with C++ at this point to decode the errors myself, and after taking a look at the single file here, I was unable to discern the issue.

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
like image 759
TankorSmash Avatar asked Aug 02 '13 04:08

TankorSmash


People also ask

How do I run MSTest in Visual Studio?

Test shortcuts Tests can be run from Test Explorer by right-clicking in the code editor on a test and selecting Run test or by using the default Test Explorer shortcuts in Visual Studio.

How do you add MSTest to a project?

On the File menu, select New > Project, or press Ctrl+Shift+N. On the Create a new project page, type unit test into the search box. Select the project template for the test framework that you want to use, for example MSTest Test Project or NUnit Test Project, and then select Next.


2 Answers

long story short: split your single project solution into 3, use a .lib of the old exe, add the projects to the appropriate paths, update the linker, and you're good to go.

AE Drew's answer helped solve my problem, but I want to put a more full solution to the question's title, in case anyone's coming from Google, especially if they are looking for a simple breakdown from a beginner's perspective.

If you only had one project in your solution that built a .exe for you, CATCH wouldn't work: your solution needs 3 projects (as far as I know) to be able to test your code.

  • Source_project, The main codebase project (in which the source code for your application resides)

  • Test_project, The test suites project (in which the REQUIRES tests appear as outlined in the above question)

  • Main_project, The project where you actually call and run the code from the source codebase.

In order to convert your original single-project solution into something that you can use in both tests and to properly run, you'll need to build a .lib or a .dll so that other projects (including other people's projects) can use the same code. Altering this answer, all it takes is to

right-click on your project in the Solution Explorer, and select > Properties.... Under Configuration Properties -> General there's an > option called Configuration Type. If you change it to [Static Library > (.lib)], your project will generate a [.lib] when it is built.

And then in the 3rd project, main_project, where you have a barebones setup from a Win32 Console Application that only contains a file that looks something like:

#include "stdafx.h"
#include "HEADER_FROM_FIRST_PROJECT.h"

int _tmain(int argc, _TCHAR* argv[])
{
   METHOD_FROM_FIRST_PROJECT();
   return 0;
}

where you import a header file from Source_project, the first project that we created (the one that used to be an exe, but is now building to a lib). But that's not going to run yet, you need to add the Source_project's directory to this projects additional directories, by right clicking the project in the Solution Explorer, under Properties > Configuration Properties > C/C++ > General > Additional Include Directories, add the source_project's folder to the list. This'll allow the #include lines to automatically search that directory for the appropriate files, saving you from having to write ../source_project/HEADER_FROM_FIRST_PROJECT.h.

Finally, the last step is to make sure that the linker will be able to actually find the objects that you are trying to include. And since we're building a .lib, we're able to do this rather simply. In the same settings dialog box as before, the Projects Properties dialog, we'll navigate instead to Configuration Properties > Linker > Input > Additional Dependencies and add the relative path to the source_project.lib file, which would look something like ../Debug/source_project.lib.

Note that if you have any .dlls that are in the old exe project, it'll need to be moved into the new main_project.

Also note that this is all very new to me and some of the terms and information are bound to be incorrect.

like image 125
TankorSmash Avatar answered Sep 18 '22 09:09

TankorSmash


Just scanning through the links you provide, I think you may need to add this line at the top of your file.

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

It looks like the functions you are trying to link are within #if defined CATCH_CONFIG_MAIN .... #endif preprocessor directives.

like image 30
A.E. Drew Avatar answered Sep 22 '22 09:09

A.E. Drew