diff options
-rw-r--r-- | Help/release/dev/ExtractGTestMacro.rst | 6 | ||||
-rw-r--r-- | Modules/GoogleTest.cmake | 175 | ||||
-rw-r--r-- | Tests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Tests/GoogleTest/CMakeLists.txt | 10 | ||||
-rw-r--r-- | Tests/GoogleTest/Test/CMakeLists.txt | 82 | ||||
-rw-r--r-- | Tests/GoogleTest/Test/main1.cxx | 30 | ||||
-rw-r--r-- | Tests/GoogleTest/Test/main2.cxx | 1 | ||||
-rw-r--r-- | Tests/GoogleTest/Test/main2.h | 6 | ||||
-rw-r--r-- | Tests/GoogleTest/Test/main3.cxx | 11 | ||||
-rw-r--r-- | Tests/GoogleTest/Test/main4.cxx | 1 | ||||
-rw-r--r-- | Tests/GoogleTest/Test/main4.h | 6 |
11 files changed, 302 insertions, 27 deletions
diff --git a/Help/release/dev/ExtractGTestMacro.rst b/Help/release/dev/ExtractGTestMacro.rst index 574982c..ff2b444 100644 --- a/Help/release/dev/ExtractGTestMacro.rst +++ b/Help/release/dev/ExtractGTestMacro.rst @@ -2,4 +2,8 @@ ExtractGTestMacro ----------------- * A new :module:`GoogleTest` module was added to provide the - ``gtest_add_tests`` macro independently of the :module:`FindGTest` module. + :command:`gtest_add_tests` function independently of the :module:`FindGTest` + module. The function was also updated to support keyword arguments, with + functionality expanded to allow a test name prefix and suffix to be + specified, the dependency on the source files to be optional and the list of + discovered test cases to be returned to the caller. diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake index 91a3a25..c9e0544 100644 --- a/Modules/GoogleTest.cmake +++ b/Modules/GoogleTest.cmake @@ -9,48 +9,162 @@ This module defines functions to help use the Google Test infrastructure. .. command:: gtest_add_tests - Automatically add tests with CTest by scanning source code for Google test - macros. + Automatically add tests with CTest by scanning source code for Google Test + macros:: - :: + gtest_add_tests(TARGET target + [SOURCES src1...] + [EXTRA_ARGS arg1...] + [WORKING_DIRECTORY dir] + [TEST_PREFIX prefix] + [TEST_SUFFIX suffix] + [SKIP_DEPENDENCY] + [TEST_LIST outVar] + ) - gtest_add_tests(<exe> <args> <files>...) + ``TARGET target`` + This must be a known CMake target. CMake will substitute the location of + the built executable when running the test. - ``<exe>`` - The path to the test executable. - ``<args>`` + ``SOURCES src1...`` + When provided, only the listed files will be scanned for test cases. If + this option is not given, the :prop_tgt:`SOURCES` property of the + specified ``target`` will be used to obtain the list of sources. + + ``EXTRA_ARGS arg1...`` + Any extra arguments to pass on the command line to each test case. + + ``WORKING_DIRECTORY dir`` + Specifies the directory in which to run the discovered test cases. If this + option is not provided, the current binary directory is used. + + ``TEST_PREFIX prefix`` + Allows the specified ``prefix`` to be prepended to the name of each + discovered test case. This can be useful when the same source files are + being used in multiple calls to ``gtest_add_test()`` but with different + ``EXTRA_ARGS``. + + ``TEST_SUFFIX suffix`` + Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of + every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` can be + specified. + + ``SKIP_DEPENDENCY`` + Normally, the function creates a dependency which will cause CMake to be + re-run if any of the sources being scanned are changed. This is to ensure + that the list of discovered tests is updated. If this behavior is not + desired (as may be the case while actually writing the test cases), this + option can be used to prevent the dependency from being added. + + ``TEST_LIST outVar`` + The variable named by ``outVar`` will be populated in the calling scope + with the list of discovered test cases. This allows the caller to do things + like manipulate test properties of the discovered tests. + + .. code-block:: cmake + + include(GoogleTest) + add_executable(FooTest FooUnitTest.cxx) + gtest_add_tests(TARGET FooTest + TEST_SUFFIX .noArgs + TEST_LIST noArgsTests + ) + gtest_add_tests(TARGET FooTest + EXTRA_ARGS --someArg someValue + TEST_SUFFIX .withArgs + TEST_LIST withArgsTests + ) + set_tests_properties(${noArgsTests} PROPERTIES TIMEOUT 10) + set_tests_properties(${withArgsTests} PROPERTIES TIMEOUT 20) + + For backward compatibility reasons, the following form is also supported:: + + gtest_add_tests(exe args files...) + + ``exe`` + The path to the test executable or the name of a CMake target. + ``args`` A ;-list of extra arguments to be passed to executable. The entire list must be passed as a single argument. Enclose it in quotes, or pass ``""`` for no arguments. - ``<files>...`` + ``files...`` A list of source files to search for tests and test fixtures. - Alternatively, use ``AUTO`` to specify that ``<exe>`` is the name + Alternatively, use ``AUTO`` to specify that ``exe`` is the name of a CMake executable target whose sources should be scanned. -Example -^^^^^^^ - -.. code-block:: cmake + .. code-block:: cmake - include(GoogleTest) - set(FooTestArgs --foo 1 --bar 2) - add_executable(FooTest FooUnitTest.cc) - gtest_add_tests(FooTest "${FooTestArgs}" AUTO) + include(GoogleTest) + set(FooTestArgs --foo 1 --bar 2) + add_executable(FooTest FooUnitTest.cxx) + gtest_add_tests(FooTest "${FooTestArgs}" AUTO) #]=======================================================================] -function(gtest_add_tests executable extra_args) - if(NOT ARGN) - message(FATAL_ERROR "Missing ARGN: Read the documentation for GTEST_ADD_TESTS") +function(gtest_add_tests) + + if (ARGC LESS 1) + message(FATAL_ERROR "No arguments supplied to gtest_add_tests()") endif() - if(ARGN STREQUAL "AUTO") - # obtain sources used for building that executable - get_property(ARGN TARGET ${executable} PROPERTY SOURCES) + + set(options + SKIP_DEPENDENCY + ) + set(oneValueArgs + TARGET + WORKING_DIRECTORY + TEST_PREFIX + TEST_SUFFIX + TEST_LIST + ) + set(multiValueArgs + SOURCES + EXTRA_ARGS + ) + set(allKeywords ${options} ${oneValueArgs} ${multiValueArgs}) + + unset(sources) + if("${ARGV0}" IN_LIST allKeywords) + cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set(autoAddSources YES) + else() + # Non-keyword syntax, convert to keyword form + if (ARGC LESS 3) + message(FATAL_ERROR "gtest_add_tests() without keyword options requires at least 3 arguments") + endif() + set(ARGS_TARGET "${ARGV0}") + set(ARGS_EXTRA_ARGS "${ARGV1}") + if(NOT "${ARGV2}" STREQUAL "AUTO") + set(ARGS_SOURCES "${ARGV}") + list(REMOVE_AT ARGS_SOURCES 0 1) + endif() + endif() + + # The non-keyword syntax allows the first argument to be an arbitrary + # executable rather than a target if source files are also provided. In all + # other cases, both forms require a target. + if(NOT TARGET "${ARGS_TARGET}" AND NOT ARGS_SOURCES) + message(FATAL_ERROR "${ARGS_TARGET} does not define an existing CMake target") + endif() + if(NOT ARGS_WORKING_DIRECTORY) + unset(workDir) + else() + set(workDir WORKING_DIRECTORY "${ARGS_WORKING_DIRECTORY}") + endif() + + if(NOT ARGS_SOURCES) + get_property(ARGS_SOURCES TARGET ${ARGS_TARGET} PROPERTY SOURCES) endif() + + unset(testList) + set(gtest_case_name_regex ".*\\( *([A-Za-z_0-9]+) *, *([A-Za-z_0-9]+) *\\).*") set(gtest_test_type_regex "(TYPED_TEST|TEST_?[FP]?)") - foreach(source ${ARGN}) - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${source}) + + foreach(source IN LISTS ARGS_SOURCES) + if(NOT ARGS_SKIP_DEPENDENCY) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${source}) + endif() file(READ "${source}" contents) string(REGEX MATCHALL "${gtest_test_type_regex} *\\(([A-Za-z_0-9 ,]+)\\)" found_tests ${contents}) foreach(hit ${found_tests}) @@ -67,7 +181,16 @@ function(gtest_add_tests executable extra_args) message(WARNING "Could not parse GTest ${hit} for adding to CTest.") continue() endif() - add_test(NAME ${test_name} COMMAND ${executable} --gtest_filter=${test_name} ${extra_args}) + add_test(NAME ${ARGS_TEST_PREFIX}${test_name}${ARGS_TEST_SUFFIX} + ${workDir} + COMMAND ${ARGS_TARGET} --gtest_filter=${test_name} ${ARGS_EXTRA_ARGS} + ) + list(APPEND testList ${ARGS_TEST_PREFIX}${test_name}${ARGS_TEST_SUFFIX}) endforeach() endforeach() + + if(ARGS_TEST_LIST) + set(${ARGS_TEST_LIST} ${testList} PARENT_SCOPE) + endif() + endfunction() diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 2f53cfc9..acd014a 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1391,6 +1391,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release if(CMake_TEST_FindGTest) add_subdirectory(FindGTest) + add_subdirectory(GoogleTest) endif() if(CMake_TEST_FindICU) diff --git a/Tests/GoogleTest/CMakeLists.txt b/Tests/GoogleTest/CMakeLists.txt new file mode 100644 index 0000000..21f8b8b --- /dev/null +++ b/Tests/GoogleTest/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME GoogleTest.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/GoogleTest/Test" + "${CMake_BINARY_DIR}/Tests/GoogleTest/Test" + ${build_generator_args} + --build-project TestGoogleTest + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) diff --git a/Tests/GoogleTest/Test/CMakeLists.txt b/Tests/GoogleTest/Test/CMakeLists.txt new file mode 100644 index 0000000..a1f08d4 --- /dev/null +++ b/Tests/GoogleTest/Test/CMakeLists.txt @@ -0,0 +1,82 @@ +cmake_minimum_required(VERSION 3.8) +project(TestGoogleTest) +include(CTest) + +include(GoogleTest) + +find_package(GTest REQUIRED) + +add_executable(test_gtest1 main1.cxx) +target_link_libraries(test_gtest1 GTest::GTest) + +# Simple test of defaults +gtest_add_tests(TARGET test_gtest1 + TEST_LIST testList +) +set(expectedTests + GoogleTest.LinksAndRuns + GoogleTest.ConditionalFail +) +if(NOT testList STREQUAL "${expectedTests}") + message(FATAL_ERROR "Expected test list: ${expectedTests} +Actual test list: ${testList}") +endif() + + +# Same target, different arguments, so use test prefix and suffix to +# differentiate from the above test cases +gtest_add_tests(TARGET test_gtest1 + TEST_LIST testList + TEST_PREFIX "set2." + TEST_SUFFIX ".foo" + EXTRA_ARGS --forceFail +) + +set(expectedTests + set2.GoogleTest.LinksAndRuns.foo + set2.GoogleTest.ConditionalFail.foo +) +if(NOT testList STREQUAL "${expectedTests}") + message(FATAL_ERROR "Expected test list: ${expectedTests} +Actual test list: ${testList}") +endif() + +set_tests_properties(set2.GoogleTest.ConditionalFail.foo PROPERTIES WILL_FAIL YES) + + +# Search specific sources to get the test list +add_executable(test_gtest2 main2.cxx) +target_link_libraries(test_gtest2 GTest::Main) +gtest_add_tests(TARGET test_gtest2 + TEST_LIST testList + SOURCES main2.h +) +set(expectedTests + GoogleTest.SomethingElse +) +if(NOT testList STREQUAL "${expectedTests}") + message(FATAL_ERROR "Expected test list: ${expectedTests} +Actual test list: ${testList}") +endif() + + +# Non-keyword form, auto-find sources +add_executable(test_gtest3 main3.cxx) +target_link_libraries(test_gtest3 GTest::Main) +gtest_add_tests(test_gtest3 "" AUTO) +if(NOT TEST GoogleTest.Foo) + message(FATAL_ERROR "Test case GoogleTest.Foo not defined") +endif() +if(NOT TEST GoogleTest.Bar) + message(FATAL_ERROR "Test case GoogleTest.Bar not defined") +endif() + + +# Non-keyword form, explicitly specified sources. Allows a non-target to be +# given for the executable. +add_executable(test_gtest4 main4.cxx) +target_link_libraries(test_gtest4 GTest::Main) +gtest_add_tests($<TARGET_FILE:test_gtest4> "" main4.h) +if(NOT TEST GoogleTest.NoKeywords) + message(FATAL_ERROR "Test case GoogleTest.NoKeywords not defined") +endif() diff --git a/Tests/GoogleTest/Test/main1.cxx b/Tests/GoogleTest/Test/main1.cxx new file mode 100644 index 0000000..03d604b --- /dev/null +++ b/Tests/GoogleTest/Test/main1.cxx @@ -0,0 +1,30 @@ +#include <gtest/gtest.h> + +#include <string> + +namespace { +bool shouldFail = false; +} + +TEST(GoogleTest, LinksAndRuns) +{ + ASSERT_TRUE(true); +} + +TEST(GoogleTest, ConditionalFail) +{ + ASSERT_FALSE(shouldFail); +} + +int main(int argc, char* argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + + if (argc > 1) { + if (argv[1] != std::string("--forceFail")) { + throw "Unexpected argument"; + } + shouldFail = true; + } + return RUN_ALL_TESTS(); +} diff --git a/Tests/GoogleTest/Test/main2.cxx b/Tests/GoogleTest/Test/main2.cxx new file mode 100644 index 0000000..05ffb4a --- /dev/null +++ b/Tests/GoogleTest/Test/main2.cxx @@ -0,0 +1 @@ +#include "main2.h" diff --git a/Tests/GoogleTest/Test/main2.h b/Tests/GoogleTest/Test/main2.h new file mode 100644 index 0000000..7243f53 --- /dev/null +++ b/Tests/GoogleTest/Test/main2.h @@ -0,0 +1,6 @@ +#include <gtest/gtest.h> + +TEST(GoogleTest, SomethingElse) +{ + ASSERT_TRUE(true); +} diff --git a/Tests/GoogleTest/Test/main3.cxx b/Tests/GoogleTest/Test/main3.cxx new file mode 100644 index 0000000..98ce13c --- /dev/null +++ b/Tests/GoogleTest/Test/main3.cxx @@ -0,0 +1,11 @@ +#include <gtest/gtest.h> + +TEST(GoogleTest, Foo) +{ + ASSERT_TRUE(true); +} + +TEST(GoogleTest, Bar) +{ + ASSERT_TRUE(true); +} diff --git a/Tests/GoogleTest/Test/main4.cxx b/Tests/GoogleTest/Test/main4.cxx new file mode 100644 index 0000000..8023bc1 --- /dev/null +++ b/Tests/GoogleTest/Test/main4.cxx @@ -0,0 +1 @@ +#include "main4.h" diff --git a/Tests/GoogleTest/Test/main4.h b/Tests/GoogleTest/Test/main4.h new file mode 100644 index 0000000..19da12a --- /dev/null +++ b/Tests/GoogleTest/Test/main4.h @@ -0,0 +1,6 @@ +#include <gtest/gtest.h> + +TEST(GoogleTest, NoKeywords) +{ + ASSERT_TRUE(true); +} |