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

Give example for having tests in production code #252

Open
nlohmann opened this issue Jul 13, 2019 · 1 comment

Comments

@nlohmann
Copy link

commented Jul 13, 2019

Description

I recently saw https://blog.jetbrains.com/rscpp/better-ways-testing-with-doctest/ where it was stated

What truly sets it apart is the ability to use it alongside your production code.

I would really like to try that. My expectation would be the following:

  • I have a large project containing of dozens of classes, each define in headers (.hpp) and implemented in source files (.cpp).
  • I would add test sections to each of the implementations (maybe at the bottom).
  • For "production" mode, I would compile the code as is - maybe defining or undefining some preprocessor symbol to switch off compilation of any test code.
  • For testing, I would like to reuse as much CMake code I already have and "just" recompile such that I have a single binary executing all the test distributed along the different implementation files.

Maybe my expectation is wrong, but in any case I would like to understand how the above quote is realizable in actual code.

@onqtam

This comment has been minimized.

Copy link
Owner

commented Jul 14, 2019

Your assumptions are correct - it would be as easy as just including the header and writing test cases!

  • You'll need to use a doctest::Context object in your main() function to support the 3 logical scenarios: run only tests/run only the application/run both
  • to remove everything testing-related from the binaries you'll need to define DOCTEST_CONFIG_DISABLE globally
  • if your application is comprised of an executable + multiple shared objects then check this out - you'll need to compile the test runner in a separate shared object and link all other shared objects and the main executable to it

To get the fastest possible compile times of asserts checkout this part of the FAQ.

As for the CMake part - yes, you'll get a single binary with all the unit tests in it, but it will be up to you to call add_test() in CMake referencing the executable in order to register a ctest. You could use the --source-file=<filters> command line option on each call to add_test() with a different source file so tests from each .cpp end up in a different ctest. In fact that is what I've done in the doctest repository - I needed a single binary in order to generate a single coverage report but I wanted separate ctests for the separate .cpp files in the examples directory - here is the loop over the sources in CMake (using the short version of the --source-file command line option).

If your program has plugins (shared objects) which are loaded at runtime and they contain tests make sure to call the run() method of a doctest::Context only after loading them - makes sense, right? :)

You could even use doctest for asserts within the actual production code - even when being executed outside of a testing context!

You could write your tests at the bottom of the .cpp files for specific components, or you could add additional source files named something like <component>_tests.cpp so tests are easily distinguished from other sources - it's up to you. You could even write test cases in header files and they will still end up registered only once.

Let me know if you have any further questions!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.