Nothing Special   »   [go: up one dir, main page]

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

Closed
nlohmann opened this issue Jul 13, 2019 · 3 comments
Closed

Give example for having tests in production code #252

nlohmann opened this issue Jul 13, 2019 · 3 comments

Comments

@nlohmann
Copy link

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
Copy link
Member
onqtam 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!

@onqtam
Copy link
Member
onqtam commented Sep 8, 2019

I'll be closing this soon if there are no further questions

@evandrocoan
Copy link

I created a gist with full example mixing production code with tests using static libraries (cmake object libraries actually). This way, you only compile the production code one time and have two main applications, the test runner and the default application which just works normally: https://gist.github.com/evandrocoan/2f53228503973b205a401c76dc9fcb13

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