Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing multiple headers. #244

Closed
thoward27 opened this issue Jun 13, 2019 · 4 comments
Closed

Testing multiple headers. #244

thoward27 opened this issue Jun 13, 2019 · 4 comments

Comments

@thoward27
Copy link

Description

I created two header files, one for some functions, another for a small string implementation, both have unit tests, and #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN. They can both be run individually, unit tests run, and pass.

Now, I want to import my functions that I created into my string source code. (#import "functions.hpp")

Doing so produces "multiple main" errors, obviously, but I cannot figure out what I should be doing differently!

Steps to reproduce

  1. Define and implement two header files: functions.hpp, string.hpp
  2. Create unit tests in both headers, using #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
  3. Attempt to import the functions.hpp in string.cpp

Extra information

I know what I am doing is wrong, but I cannot find documentation on what I should be doing.

My goal is to be at a point where I can run both sets of unit tests individually, but can also import my functions into my string class.

  • doctest version: v2.3.1
  • Operating System: Ubuntu 19.04
  • Compiler+version: g++ v8.3
@onqtam
Copy link
Member

onqtam commented Jun 13, 2019

Hi there :)

You could have something like an include guard around the definition of the DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN identifier - like this:

// functions.hpp
#pragma once

// functions stuff

#ifndef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#endif
#include "doctest.h"

TEST_CASE("your_functions_test") {
    // test your functions
}
// string.hpp
#pragma once

// string stuff

#ifndef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#endif
#include "doctest.h"

TEST_CASE("your_string_test") {
    // test your string
}

This way both headers could be used in one translation unit. If however you would want to include these headers in multiple different .cpp files in the same binary then you would need to invent a scheme with the preprocessor and the build system to have only a specific .cpp file define that identifier - like this:

// functions.hpp
#pragma once

// functions stuff

#ifdef MAIN_IN_THIS_CPP // <<<<<<<<<<<
#ifndef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#endif
#endif
#include "doctest.h"

TEST_CASE("your_functions_test") {
    // test your functions
}
// string.hpp
#pragma once

// string stuff

#ifdef MAIN_IN_THIS_CPP // <<<<<<<<<<<
#ifndef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#endif
#endif
#include "doctest.h"

TEST_CASE("your_string_test") {
    // test your string
}

Let me know if this works for you :)

@thoward27
Copy link
Author

Thanks for your response @onqtam I finally had the time to give it a try, and alas I do need the latter of your two solutions, which I avoided by splitting my test files out. (I didn't want to invent a scheme to only have one cpp define the directive)

Thanks again for your help!

@lcit
Copy link

lcit commented Jan 26, 2022

I have a similar problem. I have the following source files for testing:

main.cpp <- this contains DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
test1.cpp <- imports header.hpp
test2.cpp <- imports header.hpp

At linking time I have the error "multiple definition of ..function(.)" because the header is included in two different source file. The header has the #pragma once.

Should this work or am I doing something wrong?

@lcit
Copy link

lcit commented Jan 26, 2022

I found the problem. One of my header file of my header-only library contained non-inline (and non-template) functions.
This means that these functions end up being defined in each source files ("translation units") that import the header.
The solution is to make them inline, or templates or defined them in a source file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants