I'm new to unit testing and decided to use the Catch framework for c++ because it seemed easy to integrate with its one header file. However, I have a multifile binary search tree program (files are: main.cpp, Tree.h, Tree.hxx, TreeUnitTests.cpp, catch.hpp). I can only get my unit tests to run if I comment out my int main() function in main.cpp. I understand that it is conflicting with '#define CATCH_CONFIG_MAIN' declaration in my TreeUnitTests.cpp, but I cannot get the unit tests to run if I do not include that declaration. How can I get both to run without having to comment my main() every time I want to run the unit tests?
This is the header file I am using: https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp
And the Catch tutorial I found it on and used as a guide: https://github.com/philsquared/Catch/blob/master/docs/tutorial.md
Some relevant files for reference: main.cpp:
//******************* ASSN 01 QUESTION 02 **********************
#include "Tree.h"
#include <iostream>
using namespace std;
/*
int main()
{
//creating tree with "5" as root
Tree<int> tree(5);
tree.insert(2);
tree.insert(88);
tree.inorder();
cout << "does tree contain 2?: ";
cout << tree.find(2) << endl;
cout << "does tree contain 3?: ";
cout << tree.find(3) << endl;
Tree<int> copytree(tree);
cout << "copied original tree..." << endl;
copytree.preorder();
cout << "after deletion of 2:\n";
copytree.Delete(2);
copytree.postorder();
return 0;
}
*/
TreeUnitTests.cpp:
#include <iostream>
#include "Tree.h"
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
TEST_CASE("Pass Tests")
{
REQUIRE(1 == 1);
}
TEST_CASE("Fail test")
{
REQUIRE(1 == 0);
}
(my tests are not real tests, only to verify that the Catch framework was working correctly. I guess you can say it's a meta test)
Since you are using Visual Studio, the right approach would be to use the Configuration Manager (accessible by right clicking the solution in the Solution Explorer tool window) and create a separate solution configuration.
In the "New Solution Configuration" form, specify a meaningful name for the configuration (e.g.
UnitTesting
). There is also a drop-down list named "Copy from:" where you can select the configuration from which the settings will be copied into the new configuration. Don't leave this at<Empty>
, but rather select some source configuration which you used to build the source so far (because it will have the include folders and other settings correctly set). Make sure you also create matching project configurations for all the projects in the solution by checking the check box "Create new project configurations".Once you create the configuration, you select it the same way you would switch between Debug and Release configurations, using the toolbar drop-down list:
Click to select your new
UnitTesting
configurationNow, when you open property pages for a certain project or a file within that project (right click the file or the project, select
Properties
), you can select a specific configuration (UnitTesting
in your case), and specify certain options which will only be active for this single configuration.You can also select
All Configurations
in the property pages to apply settings to, obviously, all configurations. This is important when adding additional include directories and common preprocessor settings. If you accidentally add some include directory to the Debug configuration only, the compiler won't be able to find the header files after switching toUnitTesting
.So, to make this configuration behave differently, you can do something like:
1. Exclude
main.cpp
from theUnitTesting
build configFor example, you might right click
main.cpp
, openProperties
, and exclude the file from build in this configuration only:Excluding a file from the build for a specific configuration
2. Use a preprocessor macro to conditionally exclude the
main()
functionOr, you might open project properties and set a specific preprocessor macro which will be only defined in this configuration:
Creating a
UNIT_TESTING
macro for theUnitTesting
configuration, again MS Paint is used to add flair to the figureSo, for the latter approach, your actual
main.cpp
would be changed to something like:The first approach is neat because it doesn't require you to change production code at all, but the latter approach might be more obvious to other unsuspecting people looking at your code in Visual Studio, when they begin to wonder why certain code isn't being compiled at all. I sometimes forget a certain file is missing from a build configuration and then stare at weird compile errors for a while.
And, with the second approach, you can also easily provide your custom Catch entry point at that same place: