Welcome to the next pikoTutorial !
If you haven’t read the previous pikoTutorial on setting up a Python project with CMake, you may want to check it out first because in today’s article I’ll be using the setup we’ve done there:
project/
├── app1/
├── CMakeLists.txt
├── main.py
├── requirements.txt
├── app2/
├── CMakeLists.txt
├── main.py
├── requirements.txt
├── app3/
├── CMakeLists.txt
├── main.cpp
├── build/
├── CMakeLists.txt
However, I will extend it with the test directories for each Python application:
project/
├── app1/
├── CMakeLists.txt
├── main.py
├── requirements.txt
├── test
├── test_app.py
├── app2/
├── CMakeLists.txt
├── main.py
├── requirements.txt
├── test
├── test_app.py
├── app3/
├── CMakeLists.txt
├── main.cpp
├── build/
├── CMakeLists.txt
Adding test targets
As I was showing in the pikoTutorial about running C++ tests with CMake, to enable running unit tests with ctest
, we must extend app1/CMakeLists.txt file with add_test
call:
# specify app1 virtual environment directory
set(APP1_VENV ${CMAKE_BINARY_DIR}/app1_venv)
# create virtual environment for app1
create_venv(${APP1_VENV} ${CMAKE_SOURCE_DIR}/app1/requirements.txt)
# add custom target to run app1
add_custom_target(run_app1
COMMAND ${APP1_VENV}/bin/python ${CMAKE_SOURCE_DIR}/app1/main.py
DEPENDS ${APP1_VENV}
)
# add unit tests
add_test(
NAME app1_unit_test
COMMAND ${APP1_VENV}/bin/python -m unittest discover ${CMAKE_SOURCE_DIR}/app1/test
)
The same goes for app2/CMakeLists.txt file. To make it work, we also need to add enable_testing()
to the main CMakeLists.txt file.
Now I can run unit tests for both Python applications just by calling:
ctest
What will produce the following output:
Start 1: app1_unit_test
1/2 Test #1: app1_unit_test ................... Passed 0.07 sec
Start 2: app2_unit_test
2/2 Test #2: app2_unit_test ................... Passed 0.06 sec
Mixing unit tests between the languages
It’s time extend the configuration – let’s add tests not only for Python applications, but also for app3 which is a C++ application:
├── app3/
├── CMakeLists.txt
├── main.cpp
├── test
├── test_app.cpp
I will add the simplest C++ unit test definition to app3/CMakeLists.txt file:
# create an executable out of C++ code
add_executable(main main.cpp)
# add custom target to run app3
add_custom_target(run_app3
COMMAND ${CMAKE_BINARY_DIR}/app3/main
DEPENDS main
)
# add unit tests executable
add_executable(app3_unit_test test/test_app.cpp)
# add unit tests
add_test(
NAME app3_unit_test
COMMAND app3_unit_test
)
Now I call ctest
and voilà – both Python and C++ tests executed with a single command:
Start 1: app1_unit_test
1/3 Test #1: app1_unit_test ................... Passed 0.06 sec
Start 2: app2_unit_test
2/3 Test #2: app2_unit_test ................... Passed 0.06 sec
Start 3: app3_unit_test
3/3 Test #3: app3_unit_test ................... Passed 0.00 sec