Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,17 @@ cmake -S . -B build -DBUILD_ALL=ON -D{{ cookiecutter.module_slug | upper }}_BUIL
cmake --build build -j"$(nproc)"
```

`{{ cookiecutter.module_slug | upper }}_BUILD_TESTING` defaults to `ON` for a standalone build
and `OFF` when this module is included by a parent project. To build without
tests, configure with `-D{{ cookiecutter.module_slug | upper }}_BUILD_TESTING:BOOL=OFF`.
The standard `-DBUILD_TESTING=OFF` does not control this module's tests.
{% if cookiecutter.language == 'cpp' -%}
C++ tests require GTest (`libgtest-dev` on Debian/Ubuntu). If GTest is missing
while module tests are enabled, CMake stops with an error that names the test
option. Install GTest to run the C++ tests, or disable module tests for a
build without GTest.
{% endif -%}

{% if cookiecutter.language == 'cpp' -%}
Run C++ tests:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ int main() { holoscan::make_application<MyApp>()->run(); }
| CMake | ≥ 3.24 |
{%- if cookiecutter.language == 'cpp' %}
| C++ compiler | C++17-capable |
| GTest | Required only when C++ tests are enabled (`libgtest-dev` on Debian/Ubuntu) |
{%- endif %}
| Python | ≥ 3.11 |

Expand All @@ -113,6 +114,14 @@ cmake -S . -B build -DBUILD_ALL=ON -D{{ cookiecutter.module_slug | upper }}_BUIL
cmake --build build -j$(nproc)
```

The module's `{{ cookiecutter.module_slug | upper }}_BUILD_TESTING` option defaults to `ON` in a
standalone build. For a build without tests, set
`-D{{ cookiecutter.module_slug | upper }}_BUILD_TESTING:BOOL=OFF` when configuring.
{% if cookiecutter.language == 'cpp' -%}
With tests enabled, CMake requires GTest and reports how to disable tests if it
cannot find it. The standard `-DBUILD_TESTING=OFF` does not control this module's tests.
{% endif -%}

---

## Testing
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# SPDX-FileCopyrightText: Copyright (c) {% now 'utc', '%Y' %} {{ cookiecutter.full_name }}{% if cookiecutter.affiliation %} / {{ cookiecutter.affiliation }}{% endif %}. All rights reserved.
# SPDX-License-Identifier: {{ cookiecutter._license }}

find_package(GTest REQUIRED)
find_package(GTest QUIET)
if(NOT GTest_FOUND)
message(FATAL_ERROR
"GTest is required when {{ cookiecutter.module_slug | upper }}_BUILD_TESTING is ON. "
"Install GTest (libgtest-dev on Debian/Ubuntu), or configure with "
"-D{{ cookiecutter.module_slug | upper }}_BUILD_TESTING:BOOL=OFF to build without tests.")
endif()

add_executable(test_operators test_operators.cpp)

Expand Down
58 changes: 58 additions & 0 deletions tests/unit/test_module_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import importlib.util
import json
import shutil
import subprocess
from pathlib import Path

import pytest
Expand Down Expand Up @@ -71,3 +73,59 @@ def git(*args):
def test_direct_cookiecutter_use_cannot_pin_an_arbitrary_cli_release():
defaults = json.loads((TEMPLATE / "cookiecutter.json").read_text(encoding="utf-8"))
assert defaults["_holoscan_cli_version"] == "0"


@pytest.mark.skipif(shutil.which("cmake") is None, reason="CMake is required")
@pytest.mark.parametrize(
"tests_enabled,gtest_available", [(False, False), (True, False), (True, True)]
)
def test_cpp_test_configuration_explains_missing_gtest(tmp_path, tests_enabled, gtest_available):
"""Exercise the generated CMake test logic with and without GTest discovery."""
cpp_template = next(
(TEMPLATE / "{{cookiecutter.module_repo_name}}/tests/cpp").glob("*CMakeLists.txt*")
)
cpp_cmake = "\n".join(cpp_template.read_text(encoding="utf-8").splitlines()[2:])
cpp_cmake = cpp_cmake.replace("{{ cookiecutter.module_slug | upper }}", "MY_MOD")
cpp_cmake = cpp_cmake.replace("{{ cookiecutter.operator_slug }}", "my_mod_op")

tests_dir = tmp_path / "tests/cpp"
tests_dir.mkdir(parents=True)
(tests_dir / "CMakeLists.txt").write_text(cpp_cmake, encoding="utf-8")
(tests_dir / "test_operators.cpp").write_text("int main() { return 0; }\n", encoding="utf-8")
(tmp_path / "operators").mkdir()
(tmp_path / "CMakeLists.txt").write_text(
"cmake_minimum_required(VERSION 3.24)\n"
"project(module_test_config LANGUAGES CXX)\n"
"add_library(op INTERFACE)\n"
"add_library(holoscan::my_mod_op ALIAS op)\n"
"add_library(holoscan::core ALIAS op)\n"
'option(MY_MOD_BUILD_TESTING "Build module tests" ON)\n'
"if(MY_MOD_BUILD_TESTING)\n"
" enable_testing()\n"
" add_subdirectory(tests/cpp)\n"
"endif()\n",
encoding="utf-8",
)

cmake_args = ["cmake", "-S", str(tmp_path), "-B", str(tmp_path / "build")]
if not tests_enabled:
cmake_args.append("-DMY_MOD_BUILD_TESTING:BOOL=OFF")
if gtest_available:
cmake_modules = tmp_path / "cmake"
cmake_modules.mkdir()
(cmake_modules / "FindGTest.cmake").write_text(
"set(GTest_FOUND TRUE)\nadd_library(GTest::gtest_main INTERFACE IMPORTED)\n",
encoding="utf-8",
)
cmake_args.append(f"-DCMAKE_MODULE_PATH={cmake_modules}")
else:
cmake_args.append("-DCMAKE_DISABLE_FIND_PACKAGE_GTest=TRUE")

result = subprocess.run(cmake_args, capture_output=True, text=True, check=False)
output = result.stdout + result.stderr
if tests_enabled and not gtest_available:
assert result.returncode != 0
assert "GTest is required when MY_MOD_BUILD_TESTING is ON" in output
assert "-DMY_MOD_BUILD_TESTING:BOOL=OFF" in output
else:
assert result.returncode == 0, output
Loading