Browse Source

GoogleTest: Add TEST_FILTER arg to gtest_discover_tests

The `TEST_FILTER` argument can be used to filter tests during the
discovery phase. It combines `--gtest_filter=<expr>` with the
`--gtest_list_tests` argument when invoking the test excutable for
listing defined tests.

Fixes: #17493
Ashish Sadanandan 4 years ago
parent
commit
ea6a7dd1c2

+ 6 - 0
Help/release/dev/GoogleTest-gtest-filter.rst

@@ -0,0 +1,6 @@
+GoogleTest-gtest-filter
+-----------------------
+
+* The :module:`GoogleTest` module :command:`gtest_discover_tests`
+  function gained a ``TEST_FILTER`` option to filter tests using
+  ``--gtest_filter`` during test discovery.

+ 10 - 1
Modules/GoogleTest.cmake

@@ -151,6 +151,7 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
                          [WORKING_DIRECTORY dir]
                          [TEST_PREFIX prefix]
                          [TEST_SUFFIX suffix]
+                         [TEST_FILTER expr]
                          [NO_PRETTY_TYPES] [NO_PRETTY_VALUES]
                          [PROPERTIES name1 value1...]
                          [TEST_LIST var]
@@ -204,6 +205,12 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
     every discovered test case.  Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may
     be specified.
 
+  ``TEST_FILTER expr``
+    .. versionadded:: 3.22
+
+    Filter expression to pass to ``--gtest_filter`` argument during test
+    discovery.
+
   ``NO_PRETTY_TYPES``
     By default, the type index of type-parameterized tests is replaced by the
     actual type name in the CTest test name.  If this behavior is undesirable
@@ -411,7 +418,7 @@ function(gtest_discover_tests TARGET)
     ""
     "NO_PRETTY_TYPES;NO_PRETTY_VALUES"
     "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;DISCOVERY_TIMEOUT;XML_OUTPUT_DIR;DISCOVERY_MODE"
-    "EXTRA_ARGS;PROPERTIES"
+    "EXTRA_ARGS;PROPERTIES;TEST_FILTER"
     ${ARGN}
   )
 
@@ -475,6 +482,7 @@ function(gtest_discover_tests TARGET)
               -D "TEST_PROPERTIES=${_PROPERTIES}"
               -D "TEST_PREFIX=${_TEST_PREFIX}"
               -D "TEST_SUFFIX=${_TEST_SUFFIX}"
+              -D "TEST_FILTER=${_TEST_FILTER}"
               -D "NO_PRETTY_TYPES=${_NO_PRETTY_TYPES}"
               -D "NO_PRETTY_VALUES=${_NO_PRETTY_VALUES}"
               -D "TEST_LIST=${_TEST_LIST}"
@@ -515,6 +523,7 @@ function(gtest_discover_tests TARGET)
       "      TEST_PROPERTIES"        " [==[" "${_PROPERTIES}"             "]==]"   "\n"
       "      TEST_PREFIX"            " [==[" "${_TEST_PREFIX}"            "]==]"   "\n"
       "      TEST_SUFFIX"            " [==[" "${_TEST_SUFFIX}"            "]==]"   "\n"
+      "      TEST_FILTER"            " [==[" "${_TEST_FILTER}"            "]==]"   "\n"
       "      NO_PRETTY_TYPES"        " [==[" "${_NO_PRETTY_TYPES}"        "]==]"   "\n"
       "      NO_PRETTY_VALUES"       " [==[" "${_NO_PRETTY_VALUES}"       "]==]"   "\n"
       "      TEST_LIST"              " [==[" "${_TEST_LIST}"              "]==]"   "\n"

+ 9 - 2
Modules/GoogleTestAddTests.cmake

@@ -44,7 +44,7 @@ function(gtest_discover_tests_impl)
   cmake_parse_arguments(
     ""
     ""
-    "NO_PRETTY_TYPES;NO_PRETTY_VALUES;TEST_EXECUTABLE;TEST_WORKING_DIR;TEST_PREFIX;TEST_SUFFIX;TEST_LIST;CTEST_FILE;TEST_DISCOVERY_TIMEOUT;TEST_XML_OUTPUT_DIR"
+    "NO_PRETTY_TYPES;NO_PRETTY_VALUES;TEST_EXECUTABLE;TEST_WORKING_DIR;TEST_PREFIX;TEST_SUFFIX;TEST_LIST;CTEST_FILE;TEST_DISCOVERY_TIMEOUT;TEST_XML_OUTPUT_DIR;TEST_FILTER"
     "TEST_EXTRA_ARGS;TEST_PROPERTIES;TEST_EXECUTOR"
     ${ARGN}
   )
@@ -58,6 +58,12 @@ function(gtest_discover_tests_impl)
   set(tests)
   set(tests_buffer)
 
+  if(_TEST_FILTER)
+    set(filter "--gtest_filter=${_TEST_FILTER}")
+  else()
+    set(filter)
+  endif()
+
   # Run test executable to get list of available tests
   if(NOT EXISTS "${_TEST_EXECUTABLE}")
     message(FATAL_ERROR
@@ -66,7 +72,7 @@ function(gtest_discover_tests_impl)
     )
   endif()
   execute_process(
-    COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" --gtest_list_tests
+    COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" --gtest_list_tests ${filter}
     WORKING_DIRECTORY "${_TEST_WORKING_DIR}"
     TIMEOUT ${_TEST_DISCOVERY_TIMEOUT}
     OUTPUT_VARIABLE output
@@ -178,6 +184,7 @@ if(CMAKE_SCRIPT_MODE_FILE)
     TEST_WORKING_DIR ${TEST_WORKING_DIR}
     TEST_PREFIX ${TEST_PREFIX}
     TEST_SUFFIX ${TEST_SUFFIX}
+    TEST_FILTER ${TEST_FILTER}
     TEST_LIST ${TEST_LIST}
     CTEST_FILE ${CTEST_FILE}
     TEST_DISCOVERY_TIMEOUT ${TEST_DISCOVERY_TIMEOUT}

+ 16 - 0
Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt

@@ -0,0 +1,16 @@
+Test project .*
+    Start 27: TEST:basic\.case_foo!3
+1/4 Test #27: TEST:basic\.case_foo!3 \.+ +Passed +[0-9.]+ sec
+    Start 28: TEST:basic\.case_bar!3
+2/4 Test #28: TEST:basic\.case_bar!3 \.+ +Passed +[0-9.]+ sec
+    Start 29: TEST:basic\.disabled_case!3
+3/4 Test #29: TEST:basic\.disabled_case!3 \.+\*+Not Run \(Disabled\) +[0-9.]+ sec
+    Start 30: TEST:basic\.DISABLEDnot_really_case!3
+4/4 Test #30: TEST:basic\.DISABLEDnot_really_case!3 \.+ +Passed +[0-9.]+ sec
+
+100% tests passed, 0 tests failed out of 3
+
+Total Test time \(real\) = +[0-9.]+ sec
+
+The following tests did not run:
+.*29 - TEST:basic.disabled_case!3 \(Disabled\)

+ 9 - 0
Tests/RunCMake/GoogleTest/GoogleTest-test4-stdout.txt

@@ -0,0 +1,9 @@
+Test project .*
+    Start 31: TEST:typed/short\.case!4
+1/2 Test #31: TEST:typed/short\.case!4 \.+ +Passed +[0-9.]+ sec
+    Start 32: TEST:typed/float\.case!4
+2/2 Test #32: TEST:typed/float\.case!4 \.+ +Passed +[0-9.]+ sec
+
+100% tests passed, 0 tests failed out of 2
+
+Total Test time \(real\) = +[0-9.]+ sec

+ 18 - 0
Tests/RunCMake/GoogleTest/GoogleTest.cmake

@@ -24,6 +24,24 @@ gtest_discover_tests(
   PROPERTIES LABELS TEST2
 )
 
+gtest_discover_tests(
+  fake_gtest
+  TEST_PREFIX TEST:
+  TEST_SUFFIX !3
+  TEST_FILTER basic*
+  EXTRA_ARGS how now "\"brown\" cow"
+  PROPERTIES LABELS TEST3
+)
+
+gtest_discover_tests(
+  fake_gtest
+  TEST_PREFIX TEST:
+  TEST_SUFFIX !4
+  TEST_FILTER typed*
+  EXTRA_ARGS how now "\"brown\" cow"
+  PROPERTIES LABELS TEST4
+)
+
 add_executable(no_tests_defined no_tests_defined.cpp)
 xcode_sign_adhoc(no_tests_defined)
 

+ 14 - 0
Tests/RunCMake/GoogleTest/RunCMakeTest.cmake

@@ -40,6 +40,20 @@ function(run_GoogleTest DISCOVERY_MODE)
     --no-label-summary
   )
 
+  run_cmake_command(GoogleTest-test3
+    ${CMAKE_CTEST_COMMAND}
+    -C Debug
+    -L TEST3
+    --no-label-summary
+  )
+
+  run_cmake_command(GoogleTest-test4
+    ${CMAKE_CTEST_COMMAND}
+    -C Debug
+    -L TEST4
+    --no-label-summary
+  )
+
   run_cmake_command(GoogleTest-test-missing
     ${CMAKE_CTEST_COMMAND}
     -C Debug

+ 35 - 20
Tests/RunCMake/GoogleTest/fake_gtest.cpp

@@ -7,27 +7,42 @@ int main(int argc, char** argv)
   // it only requires that we produces output in the expected format when
   // invoked with --gtest_list_tests. Thus, we fake that here. This allows us
   // to test the module without actually needing Google Test.
+  bool is_filtered =
+    argc > 2 && std::string(argv[2]).find("--gtest_filter=") == 0;
+  bool is_basic_only =
+    is_filtered && std::string(argv[2]).find("basic*") != std::string::npos;
+  bool is_typed_only =
+    is_filtered && std::string(argv[2]).find("typed*") != std::string::npos;
+
   if (argc > 1 && std::string(argv[1]) == "--gtest_list_tests") {
-    std::cout << "basic." << std::endl;
-    std::cout << "  case_foo" << std::endl;
-    std::cout << "  case_bar" << std::endl;
-    std::cout << "  DISABLED_disabled_case" << std::endl;
-    std::cout << "  DISABLEDnot_really_case" << std::endl;
-    std::cout << "DISABLED_disabled." << std::endl;
-    std::cout << "  case" << std::endl;
-    std::cout << "DISABLEDnotreally." << std::endl;
-    std::cout << "  case" << std::endl;
-    std::cout << "typed/0.  # TypeParam = short" << std::endl;
-    std::cout << "  case" << std::endl;
-    std::cout << "typed/1.  # TypeParam = float" << std::endl;
-    std::cout << "  case" << std::endl;
-    std::cout << "value/test." << std::endl;
-    std::cout << "  case/0  # GetParam() = 1" << std::endl;
-    std::cout << "  case/1  # GetParam() = \"foo\"" << std::endl;
-    std::cout << "param/special." << std::endl;
-    std::cout << "  case/0  # GetParam() = \"semicolon;\"" << std::endl;
-    std::cout << "  case/1  # GetParam() = \"backslash\\\"" << std::endl;
-    std::cout << "  case/2  # GetParam() = \"${var}\"" << std::endl;
+    if (!is_typed_only) {
+      std::cout << "basic." << std::endl;
+      std::cout << "  case_foo" << std::endl;
+      std::cout << "  case_bar" << std::endl;
+      std::cout << "  DISABLED_disabled_case" << std::endl;
+      std::cout << "  DISABLEDnot_really_case" << std::endl;
+    }
+    if (!is_basic_only && !is_typed_only) {
+      std::cout << "DISABLED_disabled." << std::endl;
+      std::cout << "  case" << std::endl;
+      std::cout << "DISABLEDnotreally." << std::endl;
+      std::cout << "  case" << std::endl;
+    }
+    if (!is_basic_only) {
+      std::cout << "typed/0.  # TypeParam = short" << std::endl;
+      std::cout << "  case" << std::endl;
+      std::cout << "typed/1.  # TypeParam = float" << std::endl;
+      std::cout << "  case" << std::endl;
+    }
+    if (!is_basic_only && !is_typed_only) {
+      std::cout << "value/test." << std::endl;
+      std::cout << "  case/0  # GetParam() = 1" << std::endl;
+      std::cout << "  case/1  # GetParam() = \"foo\"" << std::endl;
+      std::cout << "param/special." << std::endl;
+      std::cout << "  case/0  # GetParam() = \"semicolon;\"" << std::endl;
+      std::cout << "  case/1  # GetParam() = \"backslash\\\"" << std::endl;
+      std::cout << "  case/2  # GetParam() = \"${var}\"" << std::endl;
+    }
     return 0;
   }