3

I am trying to integrate Catch unit testing to my project but it fails for the currently available

Catch v1.10.0
Generated: 2017-08-26 15:16:46.676990

Example:

test.cpp

#include "catch.hpp"

#define CATCH_CONFIG_MAIN


TEST_CASE("CATCH TEST"){
    REQUIRE(1 == 1);
}
g++ test.cpp -o test.exe -std=c++11

Error:

Undefined symbols for architecture x86_64:
  "Catch::ResultBuilder::endExpression(Catch::DecomposedExpression const&)", referenced from:
      Catch::BinaryExpression<int const&, (Catch::Internal::Operator)0, int const&>::endExpression() const in test-b77427.o
  "Catch::ResultBuilder::setResultType(bool)", referenced from:
      Catch::BinaryExpression<int const&, (Catch::Internal::Operator)0, int const&>::endExpression() const in test-b77427.o
  "Catch::ResultBuilder::useActiveException(Catch::ResultDisposition::Flags)", referenced from:
      ____C_A_T_C_H____T_E_S_T____0() in test-b77427.o
  "Catch::ResultBuilder::react()", referenced from:
      ____C_A_T_C_H____T_E_S_T____0() in test-b77427.o
  "Catch::ResultBuilder::ResultBuilder(char const*, Catch::SourceLineInfo const&, char const*, Catch::ResultDisposition::Flags, char const*)", referenced from:
      ____C_A_T_C_H____T_E_S_T____0() in test-b77427.o
  "Catch::ResultBuilder::~ResultBuilder()", referenced from:
      ____C_A_T_C_H____T_E_S_T____0() in test-b77427.o
  "Catch::SourceLineInfo::SourceLineInfo(char const*, unsigned long)", referenced from:
      ____C_A_T_C_H____T_E_S_T____0() in test-b77427.o
      ___cxx_global_var_init in test-b77427.o
  "Catch::isDebuggerActive()", referenced from:
      ____C_A_T_C_H____T_E_S_T____0() in test-b77427.o
  "Catch::AutoReg::AutoReg(void (*)(), Catch::SourceLineInfo const&, Catch::NameAndDesc const&)", referenced from:
      ___cxx_global_var_init in test-b77427.o
  "Catch::AutoReg::~AutoReg()", referenced from:
      ___cxx_global_var_init in test-b77427.o
  "Catch::toString(int)", referenced from:
      Catch::ExpressionLhs<int const&>::reconstructExpression(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) const in test-b77427.o
      Catch::BinaryExpression<int const&, (Catch::Internal::Operator)0, int const&>::reconstructExpression(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) const in test-b77427.o
  "Catch::ResultBuilder::shouldDebugBreak() const", referenced from:
      ____C_A_T_C_H____T_E_S_T____0() in test-b77427.o
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit
g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/c++/4.2.1
Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Henri Menke
  • 10,705
  • 1
  • 24
  • 42
El Dude
  • 5,328
  • 11
  • 54
  • 101
  • You have to link against that framework. – Henri Menke Aug 28 '17 at 03:01
  • 1
    The framework claims it's header only https://github.com/philsquared/Catch/blob/master/docs/tutorial.md – El Dude Aug 28 '17 at 03:02
  • 6
    You're right, sorry. But `#define CATCH_CONFIG_MAIN` has to be before `#include "catch.hpp"`. – Henri Menke Aug 28 '17 at 03:03
  • Yap, that was it.... It's counter intuitive to call a macro before including the library it's defined in? Thanks! :D – El Dude Aug 28 '17 at 03:05
  • You should post it as the answer to collect some karma... – El Dude Aug 28 '17 at 03:12
  • 2
    @ElDude think of it this way. In order for the library to see the define, the define has to come before it. It's pretty much a configuration parameter. If you wished you could also provide it by using a `-d` flag when building the program. – Paul Rooney Aug 28 '17 at 03:15
  • @PaulRooney not in that case -- `CATCH_CONFIG_MAIN` is used to generate Catch's definitions withing one of the user's .cpp files. Putting it into the compiler flags would create as many definitions as there are .cpp files including `catch.hpp`, violating the ODR. – Quentin Aug 28 '17 at 08:31
  • @Quentin absolutely didn't think of that. I guess it would not be a good idea to use the compiler flag. Although no doubt the compiler would pull you up on it. – Paul Rooney Aug 28 '17 at 09:42

1 Answers1

9

As it stands your program does not have a main function. If you compile it, the linker will complain about the absence of a main function. Since you are writing unit tests using the catch framework, you want that framework to generate a main function for you.

The catch framework looks whether CATCH_CONFIG_MAIN is defined and if yes, it generates a main function for you which runs all the tests you define. Because compilation is a linear process, the macro CATCH_CONFIG_MAIN has to be defined before including catch.hpp. Otherwise, the library will never “see” this macro.

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

TEST_CASE("CATCH TEST"){
    REQUIRE(1 == 1);
}

Live example

Henri Menke
  • 10,705
  • 1
  • 24
  • 42
  • I have the same error as OP, but I have `#define CATCH_CONFIG_MAIN` at the top of the file – Alex Buznik Aug 22 '21 at 21:30
  • @AlexBuznik Is `#define CATCH_CONFIG_MAIN` the very first line of your file? If not, please try that. – Henri Menke Aug 30 '21 at 08:02
  • Yes, it was the very first line. Anyway, the issue cleared when I included a locally-placed catch2 header file, rather than expecting for it from the CMake – Alex Buznik Aug 31 '21 at 11:36