PROTON-2135 Create pn_add_test helper for creating ctest test targets
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 08b0864..5f36ad5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,6 +37,7 @@
 find_package (CyrusSASL)
 
 enable_testing ()
+include(tests/PNAddTest.cmake)
 
 # Set up runtime checks (valgrind, sanitizers etc.)
 include(tests/RuntimeCheck.cmake)
@@ -285,17 +286,19 @@
 endmacro()
 
 if (CMAKE_SYSTEM_NAME STREQUAL Windows)
-  # No change needed for windows already use correct separator
+  # CMake uses semicolon as list separator. Change ';'->'\;'
   function(to_native_path path result)
     file (TO_NATIVE_PATH "${path}" path)
-    set (${result} ${path} PARENT_SCOPE)
+    string (REPLACE ";" "\;" path "${path}")
+    # without this, ...;last\dir\ would later combine with list separator ; into \;
+    set (${result} "${path}\;" PARENT_SCOPE)
   endfunction()
 else (CMAKE_SYSTEM_NAME STREQUAL Windows)
   # Just change ';'->':'
   function(to_native_path path result)
     file (TO_NATIVE_PATH "${path}" path)
-    string (REGEX REPLACE ";" ":" path "${path}")
-    set (${result} ${path} PARENT_SCOPE)
+    string (REPLACE ";" ":" path "${path}")
+    set (${result} "${path}" PARENT_SCOPE)
   endfunction()
 endif (CMAKE_SYSTEM_NAME STREQUAL Windows)
 
diff --git a/c/examples/CMakeLists.txt b/c/examples/CMakeLists.txt
index 87a4334..9771ec5 100644
--- a/c/examples/CMakeLists.txt
+++ b/c/examples/CMakeLists.txt
@@ -45,11 +45,12 @@
 
   set(test_env
     "PATH=${test_path}"
-    "PYTHONPATH=../../tests/py"
-    ${TEST_ENV})
+    "PYTHONPATH=../../tests/py")
 
-  add_test(
+  pn_add_test(
+    UNWRAPPED
     NAME c-example-tests
+    PREPEND_ENVIRONMENT "${test_env}"
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-    COMMAND ${PN_ENV_SCRIPT} -- ${test_env} ${PYTHON_EXECUTABLE} testme -v)
+    COMMAND ${PYTHON_EXECUTABLE} testme -v)
 endif()
diff --git a/c/tests/CMakeLists.txt b/c/tests/CMakeLists.txt
index 137ac15..a0550cc 100644
--- a/c/tests/CMakeLists.txt
+++ b/c/tests/CMakeLists.txt
@@ -20,9 +20,9 @@
 configure_file(test_config.h.in test_config.h)
 include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/tests/include)
 if (WIN32)
-  set(test_env "PATH=$<TARGET_FILE_DIR:qpid-proton-core>" ${TEST_ENV})
+  set(test_env "PATH=$<TARGET_FILE_DIR:qpid-proton-core>")
 else()
-  set(test_env ${TEST_ENV})
+  set(test_env "")
   set(platform_test_src ssl_test.cpp)
 endif()
 
@@ -45,9 +45,12 @@
     add_executable(${exe} $<TARGET_OBJECTS:test_main> pn_test.cpp ${ARGN})
     set_target_properties(${exe} PROPERTIES
       COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARNING_FLAGS}")
-    add_test(NAME ${exe} COMMAND ${PN_ENV_SCRIPT} -- ${test_env} ${TEST_EXE_PREFIX_CMD} $<TARGET_FILE:${exe}>)
-    set_tests_properties(${exe} PROPERTIES
-      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+    pn_add_test(
+      EXECUTABLE
+      NAME ${exe}
+      PREPEND_ENVIRONMENT ${test_env}
+      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+      COMMAND $<TARGET_FILE:${exe}>)
   endmacro()
 
   ## Tests that depend only on qpid-proton-core
@@ -83,8 +86,12 @@
     if (THREADERCISER)
       add_executable(c-threaderciser threaderciser.c)
       set_target_properties(c-threaderciser PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} ${C_WARNING_FLAGS}")
-      add_test(NAME c-threaderciser COMMAND ${PN_ENV_SCRIPT} -- ${test_env} ${TEST_EXE_PREFIX_CMD} $<TARGET_FILE:c-threaderciser>)
-      set_tests_properties(c-threaderciser PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+      pn_add_test(
+        EXECUTABLE
+        NAME c-threaderciser
+        PREPEND_ENVIRONMENT ${test_env}
+        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+        COMMAND $<TARGET_FILE:c-threaderciser>)
       target_link_libraries (c-threaderciser qpid-proton-proactor)
       find_library(Pthread_LIBRARY pthread)
       if (Pthread_LIBRARY)
@@ -100,11 +107,14 @@
 
     set(pypath "${CMAKE_SOURCE_DIR}/tests/py")
 
-    # unset TEST_EXE_PREFIX as valgrind does not run succesfully when fds are limited
-    add_test(
-        NAME c-fdlimit-tests
-        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-        COMMAND ${PN_ENV_SCRIPT} -- "PATH=${path}" "PYTHONPATH=${pypath}" ${test_env} "TEST_EXE_PREFIX=" ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/fdlimit.py)
+    # unset TEST_EXE_PREFIX as valgrind does not run successfully when fds are limited
+    pn_add_test(
+      UNWRAPPED
+      NAME c-fdlimit-tests
+      PREPEND_ENVIRONMENT "PATH=${path}" "PYTHONPATH=${pypath}" "${test_env}"
+      APPEND_ENVIRONMENT "TEST_EXE_PREFIX="
+      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+      COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/fdlimit.py)
   endif(HAS_PROACTOR)
 else (CMAKE_CXX_COMPILER)
   message(WARNING "No C++ compiler, some C library tests were not built")
diff --git a/c/tests/fuzz/CMakeLists.txt b/c/tests/fuzz/CMakeLists.txt
index 5db916d..2fd19b9 100644
--- a/c/tests/fuzz/CMakeLists.txt
+++ b/c/tests/fuzz/CMakeLists.txt
@@ -55,9 +55,16 @@
       set(file_lines "${file_lines}${f}\n")
     endforeach()
     file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${test}-files" "${file_lines}")
-    add_test (NAME ${test} COMMAND ${PN_ENV_SCRIPT} -- ${test_env} ${TEST_EXE_PREFIX_CMD} $<TARGET_FILE:${test}> "@${CMAKE_CURRENT_BINARY_DIR}/${test}-files")
+    pn_add_test(
+      EXECUTABLE
+      NAME ${test}
+      PREPEND_ENVIRONMENT ${test_env}
+      COMMAND $<TARGET_FILE:${test}> "@${CMAKE_CURRENT_BINARY_DIR}/${test}-files")
   else ()
-    add_test (NAME ${test} COMMAND $<TARGET_FILE:${test}> -runs=1 ${CMAKE_CURRENT_SOURCE_DIR}/${test}>)
+    pn_add_test(
+      EXECUTABLE
+      NAME ${test}
+      COMMAND $<TARGET_FILE:${test}> -runs=1 ${CMAKE_CURRENT_SOURCE_DIR}/${test}>)
   endif ()
 endmacro(pn_add_fuzz_test)
 
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 5b7399e..80d6d89 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -248,7 +248,7 @@
   DESTINATION ${LIB_INSTALL_DIR}/cmake/ProtonCpp)
 
 set(testdata "${CMAKE_CURRENT_BINARY_DIR}/testdata")
-set(test_env ${TEST_ENV})
+set(test_env "")
 
 # SASL configuration for tests
 if(CyrusSASL_Saslpasswd_EXECUTABLE)
@@ -272,8 +272,12 @@
 macro(add_cpp_test test)
   add_executable (${test} src/${test}.cpp)
   target_link_libraries (${test} qpid-proton-cpp ${PLATFORM_LIBS})
-  add_test (NAME cpp-${test}
-    COMMAND ${PN_ENV_SCRIPT} -- ${test_env} ${TEST_EXE_PREFIX_CMD} $<TARGET_FILE:${test}> ${ARGN})
+  pn_add_test(
+    EXECUTABLE
+    NAME cpp-${test}
+    APPEND_ENVIRONMENT ${test_env}
+    COMMAND $<TARGET_FILE:${test}>
+    ${ARGN})
 endmacro(add_cpp_test)
 
 add_cpp_test(codec_test)
@@ -305,11 +309,11 @@
 target_link_libraries(cpp-test qpid-proton-cpp ${PLATFORM_LIBS})
 
 macro(add_catch_test tag)
-  add_test (
+  pn_add_test(
+    EXECUTABLE
     NAME cpp-${tag}-test
-    COMMAND ${PN_ENV_SCRIPT} -- ${test_env}
-    ${TEST_EXE_PREFIX_CMD} $<TARGET_FILE:cpp-test> "[${tag}]"
-    )
+    APPEND_ENVIRONMENT ${test_env}
+    COMMAND $<TARGET_FILE:cpp-test> "[${tag}]")
 endmacro(add_catch_test)
 
 add_catch_test(url)
diff --git a/cpp/examples/CMakeLists.txt b/cpp/examples/CMakeLists.txt
index 226f6b2..4c6dc9f 100644
--- a/cpp/examples/CMakeLists.txt
+++ b/cpp/examples/CMakeLists.txt
@@ -115,18 +115,21 @@
   set(test_env
     "PATH=${test_path}"
     "PYTHONPATH=../../tests/py"
-    "HAS_CPP11=$<$<BOOL:${HAS_ENOUGH_CPP11}>:1>"
-    ${TEST_ENV})
+    "HAS_CPP11=$<$<BOOL:${HAS_ENOUGH_CPP11}>:1>")
 
-  add_test(
+  pn_add_test(
+    UNWRAPPED
     NAME cpp-example-container
+    PREPEND_ENVIRONMENT "${test_env}"
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-    COMMAND ${PN_ENV_SCRIPT} -- ${test_env} ${PYTHON_EXECUTABLE} testme -v ContainerExampleTest)
+    COMMAND ${PYTHON_EXECUTABLE} testme -v ContainerExampleTest)
 
   if (NOT SSL_IMPL STREQUAL none)
-    add_test(
+    pn_add_test(
+      UNWRAPPED
       NAME cpp-example-container-ssl
+      PREPEND_ENVIRONMENT "${test_env}"
       WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-      COMMAND ${PN_ENV_SCRIPT} -- ${test_env} ${PYTHON_EXECUTABLE}  testme -v ContainerExampleSSLTest)
+      COMMAND ${PYTHON_EXECUTABLE} testme -v ContainerExampleSSLTest)
   endif()
 endif()
diff --git a/go/CMakeLists.txt b/go/CMakeLists.txt
index 4c61eb8..e252212 100644
--- a/go/CMakeLists.txt
+++ b/go/CMakeLists.txt
@@ -58,7 +58,7 @@
           COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/../go.mod ${GOPATH}/../go.mod)
 
   # Following are CACHE INTERNAL so examples/CMakeLists.txt can see them.
-  set(GO_ENV ${PN_ENV_SCRIPT} --
+  set(GO_ENV
     "GOPATH=${GOPATH}"
     "CGO_CFLAGS=-I${PN_C_INCLUDE_DIR}"
     "CGO_LDFLAGS=-L${PN_C_LIBRARY_DIR}"
@@ -66,7 +66,7 @@
     "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
     CACHE INTERNAL "Run a command with Go environment variables")
 
-  set(GO ${GO_ENV} ${GO_EXE} CACHE INTERNAL "Run go with environment set")
+  set(GO ${PN_ENV_SCRIPT} -- ${GO_ENV} ${GO_EXE} CACHE INTERNAL "Run go with environment set")
 
   set(GO_BUILD ${GO} build ${GO_BUILD_FLAGS} ${GO_RPATH_FLAGS} CACHE INTERNAL "Run go build")
   set(GO_INSTALL ${GO} install ${GO_BUILD_FLAGS} CACHE INTERNAL "Run go install" )
@@ -81,7 +81,8 @@
     WORKING_DIRECTORY $ENV{PWD})
 
   add_test(
-    NAME go-test COMMAND ${GO_TEST} $ENV{PWD}/go/pkg/...
+    NAME go-test
+    COMMAND ${GO_TEST} $ENV{PWD}/go/pkg/...
     WORKING_DIRECTORY $ENV{PWD})
 
   # Clean up go output directories.
diff --git a/go/examples/CMakeLists.txt b/go/examples/CMakeLists.txt
index c9aba01..7f4bd2a 100644
--- a/go/examples/CMakeLists.txt
+++ b/go/examples/CMakeLists.txt
@@ -42,13 +42,16 @@
     COMMAND ${GO_TEST} -c -o ${test_exe} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.go
     WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
 
-  add_test(
+  pn_add_test(
+    UNWRAPPED
     NAME go-example-electron
-    COMMAND ${GO_ENV} ${test_exe} -dir ${CMAKE_CURRENT_BINARY_DIR}/electron -broker broker)
+    PREPEND_ENVIRONMENT ${GO_ENV}
+    COMMAND ${test_exe} -dir ${CMAKE_CURRENT_BINARY_DIR}/electron -broker broker)
 
-  add_test(
+  pn_add_test(
+    UNWRAPPED
     NAME go-example-proton
-    COMMAND ${GO_ENV} ${test_exe} -dir ${CMAKE_CURRENT_BINARY_DIR}/electron -broker ../proton/broker)
-
+    PREPEND_ENVIRONMENT ${GO_ENV}
+    COMMAND ${test_exe} -dir ${CMAKE_CURRENT_BINARY_DIR}/electron -broker ../proton/broker)
   list(APPEND ADDITIONAL_MAKE_CLEAN_FILES ${examples})
 endif()
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 942d55b..87057d8 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -237,12 +237,14 @@
   set (python_coverage_options -m coverage run)
 endif(CMAKE_BUILD_TYPE MATCHES "Coverage")
 
-add_test (NAME python-test
-  COMMAND ${PN_ENV_SCRIPT}
-  "PATH=${py_path}" "PYTHONPATH=${py_pythonpath}"
-  "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
-  ${TEST_ENV}
-  ${TEST_WRAP_PREFIX_CMD} ${PYTHON_EXECUTABLE} -- ${python_coverage_options} "${py_tests}/proton-test")
+pn_add_test(
+  INTERPRETED
+  NAME python-test
+  PREPEND_ENVIRONMENT
+    "PATH=${py_path}"
+    "PYTHONPATH=${py_pythonpath}"
+    "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
+  COMMAND ${PYTHON_EXECUTABLE} ${python_coverage_options} -- "${py_tests}/proton-test")
 set_tests_properties(python-test PROPERTIES PASS_REGULAR_EXPRESSION "Totals: .* 0 failed")
 
 check_python_module("tox" TOX_MODULE_FOUND)
@@ -265,13 +267,14 @@
       configure_file(
         "${CMAKE_CURRENT_SOURCE_DIR}/tox.ini.in"
         "${CMAKE_CURRENT_BINARY_DIR}/tox.ini")
-      add_test (NAME python-tox-test
-        COMMAND ${PN_ENV_SCRIPT} --
-        "PATH=${py_path}"
-        "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
-        "SWIG=${SWIG_EXECUTABLE}"
-        ${TEST_ENV}
-        ${TEST_WRAP_PREFIX_CMD} ${PYTHON_EXECUTABLE} -m tox)
+      pn_add_test(
+        INTERPRETED
+        NAME python-tox-test
+        PREPEND_ENVIRONMENT
+          "PATH=${py_path}"
+          "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
+          "SWIG=${SWIG_EXECUTABLE}"
+        COMMAND ${PYTHON_EXECUTABLE} -m tox)
       set_tests_properties(python-tox-test
         PROPERTIES
         PASS_REGULAR_EXPRESSION "Totals: .* ignored, 0 failed"
diff --git a/ruby/CMakeLists.txt b/ruby/CMakeLists.txt
index cd03305..79e7dcd 100644
--- a/ruby/CMakeLists.txt
+++ b/ruby/CMakeLists.txt
@@ -124,21 +124,24 @@
   set(test_env
     "PATH=${PATH}"
     "RUBYLIB=${RUBYLIB}"
-    "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
-    ${TEST_ENV})
+    "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}")
 
   macro(add_ruby_test script)
     get_filename_component(name ${script} NAME_WE)
     string(REPLACE "_" "-" name "ruby-${name}")
-    add_test(
+    pn_add_test(
+      INTERPRETED
       NAME ${name}
-      COMMAND ${PN_ENV_SCRIPT} -- ${test_env} ${TEST_WRAP_PREFIX_CMD} ${RUBY_EXECUTABLE} ${script} -v
+      PREPEND_ENVIRONMENT ${test_env}
+      COMMAND ${RUBY_EXECUTABLE} ${script} -v
       ${ARGN})
   endmacro()
 
-  add_test(
+  pn_add_test(
+    UNWRAPPED
     NAME ruby-example-test
-    COMMAND ${PN_ENV_SCRIPT} -- ${test_env} ${RUBY_EXECUTABLE} testme -v
+    PREPEND_ENVIRONMENT ${test_env}
+    COMMAND ${RUBY_EXECUTABLE} testme -v
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/examples)
 
   file(GLOB TESTS tests/test_*.rb)
diff --git a/tests/PNAddTest.cmake b/tests/PNAddTest.cmake
new file mode 100644
index 0000000..a4c2257
--- /dev/null
+++ b/tests/PNAddTest.cmake
@@ -0,0 +1,62 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Helper function to define execution environment for ctest test targets
+
+include(CMakeParseArguments)
+include(CTest)
+
+function(pn_add_test)
+  set(options EXECUTABLE INTERPRETED UNWRAPPED IGNORE_ENVIRONMENT)
+  set(oneValueArgs NAME COMMAND WORKING_DIRECTORY)
+  set(multiValueArgs PREPEND_ENVIRONMENT APPEND_ENVIRONMENT)
+
+  # Semicolon is CMake list separator and path separator on Windows; cmake_parse_arguments flattens nested lists!
+  # Replace \; to /////, call cmake_parse_arguments, then replace back where it matters; ///// is unlikely to appear
+  STRING(REPLACE \\\; ///// escaped_ARGN "${ARGN}")
+  cmake_parse_arguments(pn_add_test "${options}" "${oneValueArgs}" "${multiValueArgs}" "${escaped_ARGN}")
+
+  set(escaped_environment ${pn_add_test_PREPEND_ENVIRONMENT} ${TEST_ENV} ${pn_add_test_APPEND_ENVIRONMENT})
+  STRING(REPLACE ///// \\\; environment "${escaped_environment}")
+
+  if (pn_add_test_IGNORE_ENVIRONMENT)
+    set (ignore_environment "--ignore_environment")
+  else(pn_add_test_IGNORE_ENVIRONMENT)
+    set (ignore_environment "")
+  endif(pn_add_test_IGNORE_ENVIRONMENT)
+
+  if (pn_add_test_UNWRAPPED)
+    set (wrapper "")
+  elseif(pn_add_test_INTERPRETED)
+    set (wrapper "${TEST_WRAP_PREFIX_CMD}")
+  elseif(pn_add_test_EXECUTABLE)
+    set (wrapper "${TEST_EXE_PREFIX_CMD}")
+  else()
+    message(FATAL_ERROR "pn_add_test requires one of EXECUTABLE INTERPRETED UNWRAPPED")
+  endif()
+
+  add_test (
+    NAME "${pn_add_test_NAME}"
+    COMMAND ${PN_ENV_SCRIPT} ${ignore_environment} -- ${environment} ${wrapper} ${pn_add_test_COMMAND} ${pn_add_test_UNPARSED_ARGUMENTS}
+    WORKING_DIRECTORY "${pn_add_test_WORKING_DIRECTORY}"
+  )
+
+  # TODO jdanek 2020-01-17: this could be used instead of env.py, it looks CMake 2.8.12 compatible
+  #set_tests_properties("${pn_add_test_NAME}" PROPERTIES ENVIRONMENT "${environment}")
+endfunction(pn_add_test)
diff --git a/tests/RuntimeCheck.cmake b/tests/RuntimeCheck.cmake
index 2259691..aed4900 100644
--- a/tests/RuntimeCheck.cmake
+++ b/tests/RuntimeCheck.cmake
@@ -117,7 +117,7 @@
 if(TEST_EXE_PREFIX)
   # Add TEST_EXE_PREFIX to TEST_ENV so test runner scripts can use it.
   list(APPEND TEST_ENV "TEST_EXE_PREFIX=${TEST_EXE_PREFIX}")
-  # Make a CMake-list form of TEST_EXE_PREFIX for add_test() commands
+  # Make a CMake-list form of TEST_EXE_PREFIX for (pn_)add_test() commands
   separate_arguments(TEST_EXE_PREFIX_CMD UNIX_COMMAND "${TEST_EXE_PREFIX}")
 endif()
 separate_arguments(TEST_WRAP_PREFIX_CMD UNIX_COMMAND "${TEST_WRAP_PREFIX}")
diff --git a/tests/share/CMakeLists.txt b/tests/share/CMakeLists.txt
index 924ce37..ad14306 100644
--- a/tests/share/CMakeLists.txt
+++ b/tests/share/CMakeLists.txt
@@ -24,7 +24,7 @@
 enable_testing()
 include("tests/RuntimeCheck.cmake")
 
-# ind example sub-directories that contain "CMakeLists.txt" or "testme"
+# find example sub-directories that contain "CMakeLists.txt" or "testme"
 set(ex_dir "${CMAKE_SOURCE_DIR}/examples")
 file(GLOB subs ${ex_dir}/*)
 foreach(dir ${subs})
@@ -34,7 +34,8 @@
     add_subdirectory(${dir})
   elseif(EXISTS ${dir}/testme)
     # Has a "testme" script to run example tests.
-    add_test(
+    pn_add_test(
+      UNWRAPPED
       NAME ${ex}-example-tests
       COMMAND ${dir}/testme
       WORKING_DIRECTORY ${dir})