Differences in set_property vs set_tests_properties for discovered gtest tests

My project builds a gtest binary. I have a set of test lists - text files of test names. If a test name is in list foo, I want to add label foo to that discovered test. I can do this by adding a CTest script to TEST_INCLUDE_FILES.

Properties can be set on tests with set_property or set_tests_properties. I want to use set_property because it has an APPEND form. If a test is in multiple lists, I want to add multiple labels, and it is simplest to do this with multiple loops. Unfortunately, set_property(TEST test …) always fails on gtest discovered tests with “set_property given TEST names that do not exist”.

Conversely, set_tests_properties says in its documentation “If the test is not found, CMake will report an error,” but this is not true. set_tests_properties() can be called for anything in the CTest script, and invalid names will be ignored.

My guess is that some exception was added for set_tests_properties to work on gtest discovered tests before they really exist, and this exception does not apply to set_property. But this is pure speculation.

Is this the intended behavior? Ideally, I want to be able to use set_property and its append form, and I also don’t want errors for test names that aren’t found.

Quick reproduction:
hello_test.cc

#include <gtest/gtest.h>

// Demonstrate some basic assertions.
TEST(HelloTest, BasicAssertions) {
  // Expect two strings not to be equal.
  EXPECT_STRNE("hello", "world");
  // Expect equality.
  EXPECT_EQ(7 * 6, 42);
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.26)
project(repro)

set(CMAKE_CXX_STANDARD 14)

include(FetchContent)
FetchContent_Declare(
  googletest
  URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)

enable_testing()

add_executable(hello_test
    hello_test.cc
)
target_link_libraries(hello_test GTest::gtest_main)

include(GoogleTest)
gtest_discover_tests(hello_test)

set_property(DIRECTORY APPEND PROPERTY
TEST_INCLUDE_FILES ${CMAKE_CURRENT_LIST_DIR}/LabelTests.cmake
)

LabelTests.cmake

set_tests_properties("HelloTest.BasicAssertions" PROPERTIES LABELS foo)
set_tests_properties("fake-test" PROPERTIES LABELS foo)

set_property(TEST "HelloTest.BasicAssertions" APPEND PROPERTY LABELS bar)

I am not 100% certain, but I believe you can’t call set_property() in a script run at test time. It expects the full internal data available only at configure time. The set_tests_properties() command is supported at test time though. I don’t know the details, but I’ve hit a situation that sounds similar to yours in the past, and that’s my recollection of what I found back then.

The “detail” is that CTest reimplements the minimum bits for the commands that show up in the generated CTest scripts; they are not the CMake commands of the same name.