I have started a simple C++ project that uses Bazel as build system and would like to add Catch2 to it, as test framework.
This is what my project looks like so far:
WORKSPACE -> empty file
src/
Money.hpp
Money.cpp
BUILD
where BUILD is just
cc_library(
name = "Money",
srcs = ["Money.cpp"],
hdrs = ["Money.hpp"]
)
I would like to be able to create tests for each cc_library
, in this case for Money
. I tried setting it up but got confused with Catch2 main. Any advice on how to do this best is appreciated!
After some back and forth I managed to get this working, for Bazel 0.16.1 and Catch2 2.4.0.
First let's create directory test/
next to src/
, to keep our tests there.
In order to use Catch2, we need to download catch.hpp
. Catch2 is header only library, meaning that one file is all we need. I put it in test/vendor/catch2/
.
Then, we need to define to bazel how to use it. In test/vendor/catch2
we create following BUILD file:
cc_library(
name = "catch2",
hdrs = ["catch.hpp"],
visibility = ["//test:__pkg__"]
)
Now Bazel recognizes Catch2 as a library. We added visibility attribute, so that it can be used from the //test
package (which is defined by BUILD in /test
directory).
Next, Catch2 requires us to define one translation unit with correctly defined main method. Following their instructions, we create test/main.cpp
file:
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
Now, we write our test, in test/Money.test.cpp
:
#include "catch.hpp"
#include "Money.hpp"
TEST_CASE("Money works.") {
...
}
Finally, we need to explain to Bazel how to build all this. Notice that we directly included Money.hpp and catch.hpp in our files, with no relative path, so that is also smth we need to keep in mind.
We create following test/BUILD
file:
# We describe to Bazel how to build main.cpp.
# It includes "catch.hpp" directly, so we need to add
# "-Itest/vendor/catch2" compiler option.
cc_library(
name = "catch-main",
srcs = ["main.cpp"],
copts = ["-Itest/vendor/catch2"],
deps = [
"//test/vendor/catch2"
]
)
# Here we define our test. It needs to build together with the catch2
# main that we defined above, so we add it to deps. We directly
# include src/Money.hpp and test/vendor/catch2/catch.hpp in
# Money.test.cpp, so we need to add their parent directories as copts.
# We also add Money and catch2 as dependencies.
cc_test(
name = "Money",
srcs = ["Money.test.cpp"],
copts = ["-Itest/vendor/catch2/", "-Isrc/"],
deps = [
# Or "//test/vendor/catch2:catch2", it is the same.
"//test/vendor/catch2",
"catch-main",
"//src:Money"
]
)
# Test suite that runs all the tests.
test_suite(
name = "all-tests",
tests = [
"Money"
]
)
Finally, we just need to add visibility
attribute to src/BUILD
so that it can be accessed from tests. We modify src/BUILD
to look like this:
cc_library(
name = "Money",
srcs = ["Money.cpp"],
hdrs = ["Money.hpp"],
visibility = ["//test:__pkg__"]
)
Final file structure looks like this:
WORKSPACE
src/
Money.hpp
Money.cpp
BUILD
test/
BUILD
main.cpp
Money.test.cpp
vendor/
catch2/
catch.hpp
BUILD
Now you can run your tests with bazel test //test:all-tests
!
I created Github repo with this example, you can check it out here. I also turned it into a blog post.