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.txtHowever, 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.txtAdding 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:
ctestWhat 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 secMixing 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.cppI 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 secRead also:
- Storing your ATTiny program in…EEPROM?
- Bug of the week #12
- Sharing variable between bash scripts
- A 40-line LLM-based bash command executor in Python
- GTest and short-circuit evaluation in C++
- AI is powerful. Snippets are instant.
- From AUTOSAR to S-Core: the first C++ pub/sub implementation
- How to write Arduino Uno code with Python?
- Combining Bazel with Docker
- Running commands with timeout on Linux
- Running Python unit tests with CMake
- Thirdparty dependencies with FetchContent
- Bug of the week #11
- Combining CMake with Docker
- How to search the internet from Linux terminal?
- Folding expressions in C++
- How to derive from an enum in Python?
- Bug of the week #10
- Trying ROS2: client/server within a single container
- Make C++ a better place #4: Go as an alternative
- How to convert hex to dec in Linux terminal?
- Setting up a Python project with CMake
- Separating builds for different configs with Bazel
- Trying ROS2: pub/sub within a single container
- Bug of the week #9
- UDP multicasting with Python
- Destruction order vs thread safety in C++
- Let’s review some code: C++ #2
- Make C++ a better place #3: D as an alternative
- Registering callback using std::function in C++
- Bug of the week #8
- TCP client/server with Python
- Simple menus in Bash scripts with select
- Calling member function on a nullptr in C++
- Bug of the week #7
- Python lru_cache explained
- How to dockerize a Python application?
- Make C++ a better place #2: CppFront as an alternative
- Parameters combinations in GoogleTest
- Data transfer with curl
- Python reduce explained
- Bug of the week #6
- Custom literals in C++
- Linux and hash command
- 5 Python good practices which make life easier
- Let’s review some code: Python #1
- Make C++ a better place #1: What does better mean
- Enums vs enum class in C++
- Bug of the week #5
- UDP client/server with Python
- Hard links in Linux
- Functions calling order in unit tests in C++
- Bug of the week #4
- Yield in Python – state machines, coroutines and more
- Copy files from another branch with Git
- Make C++ a better place #0: Introduction
- 5 misconceptions about std::move in C++
- How to use xargs on Linux?
- How to test method call order with unittest in Python?
- Bug of the week #3









