1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
# Copyright 2017 Open Source Robotics Foundation, Inc.
#
# Licensed 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.
#
# Add a pytest test.
#
# :param testname: the name of the test
# :type testname: string
# :param path: the path to a file or folder where ``pytest`` should be invoked
# on
# :type path: string
# :param NOCAPTURE: disable pytest output capturing.
# Sets the pytest option '-s'.
# :type NOCAPTURE: option
# :param SKIP_TEST: if set mark the test as being skipped
# :type SKIP_TEST: option
# :param PYTHON_EXECUTABLE: Python executable used to run the test.
# It defaults to the CMake executable target Python3::Interpreter.
# :type PYTHON_EXECUTABLE: string
# :param RUNNER: the path to the test runner script (default: see ament_add_test).
# :type RUNNER: string
# :param TIMEOUT: the test timeout in seconds,
# default defined by ``ament_add_test()``
# :type TIMEOUT: integer
# :param WERROR: If ON, then treat warnings as errors. Default: OFF.
# :type WERROR: bool
# :param WORKING_DIRECTORY: the working directory for invoking the
# command in, default defined by ``ament_add_test()``
# :type WORKING_DIRECTORY: string
# :param ENV: list of env vars to set; listed as ``VAR=value``
# :type ENV: list of strings
# :param APPEND_ENV: list of env vars to append if already set, otherwise set;
# listed as ``VAR=value``
# :type APPEND_ENV: list of strings
# :param APPEND_LIBRARY_DIRS: list of library dirs to append to the appropriate
# OS specific env var, a la LD_LIBRARY_PATH
# :type APPEND_LIBRARY_DIRS: list of strings
#
# @public
#
function(ament_add_pytest_test testname path)
cmake_parse_arguments(ARG
"NOCAPTURE;SKIP_TEST"
"PYTHON_EXECUTABLE;RUNNER;TIMEOUT;WERROR;WORKING_DIRECTORY"
"APPEND_ENV;APPEND_LIBRARY_DIRS;ENV"
${ARGN})
if(ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "ament_add_pytest_test() called with unused arguments: "
"${ARG_UNPARSED_ARGUMENTS}")
endif()
# check arguments
if(NOT IS_ABSOLUTE "${path}")
set(path "${CMAKE_CURRENT_SOURCE_DIR}/${path}")
endif()
# only check existence of path if it doesn't contain generator expressions
string(FIND "${path}" "$<" index)
if(index EQUAL -1 AND NOT EXISTS "${path}")
message(FATAL_ERROR
"ament_add_pytest_test() the path '${path}' does not exist")
endif()
if(NOT ARG_PYTHON_EXECUTABLE)
set(ARG_PYTHON_EXECUTABLE Python3::Interpreter)
endif()
get_executable_path(python_interpreter "${ARG_PYTHON_EXECUTABLE}" BUILD)
# ensure pytest is available
ament_has_pytest(has_pytest QUIET PYTHON_EXECUTABLE "${ARG_PYTHON_EXECUTABLE}")
if(NOT has_pytest)
message(WARNING
"The Python module 'pytest' was not found, pytests cannot be run. "
"On Linux, install the 'python3-pytest' package. "
"On other platforms, install 'pytest' using pip.")
return()
endif()
set(result_file "${AMENT_TEST_RESULTS_DIR}/${PROJECT_NAME}/${testname}.xunit.xml")
set(cmd
"${python_interpreter}"
"-u" # unbuffered stdout and stderr
"-m" "pytest"
"${path}"
# store last failed tests
"-o" "cache_dir=${CMAKE_CURRENT_BINARY_DIR}/ament_cmake_pytest/${testname}/.cache"
# junit arguments
"--junit-xml=${result_file}"
"--junit-prefix=${PROJECT_NAME}"
)
set(ARG_ENV PYTHONDONTWRITEBYTECODE=1 ${ARG_ENV})
if(ARG_NOCAPTURE)
# disable output capturing
list(APPEND cmd "-s")
endif()
if(ARG_WERROR)
# treat warnings as errors
list(APPEND cmd "-We")
endif()
# enable pytest coverage by default if the package test_depends on python3-pytest-cov
if("python3-pytest-cov" IN_LIST ${PROJECT_NAME}_TEST_DEPENDS)
set(coverage_default ON)
else()
set(coverage_default OFF)
endif()
option(AMENT_CMAKE_PYTEST_WITH_COVERAGE
"Generate coverage information for Python tests"
${coverage_default})
if(AMENT_CMAKE_PYTEST_WITH_COVERAGE)
# get pytest-cov version, if available
ament_get_pytest_cov_version(pytest_cov_version
PYTHON_EXECUTABLE "${ARG_PYTHON_EXECUTABLE}"
)
if(NOT pytest_cov_version)
message(WARNING
"The Python module 'pytest-cov' was not found, test coverage will not be produced. "
"On Linux, install the 'python3-pytest-cov' package. "
"On other platforms, install 'pytest-cov' using pip.")
else()
set(coverage_directory "${CMAKE_CURRENT_BINARY_DIR}/pytest_cov/${testname}")
file(MAKE_DIRECTORY "${coverage_directory}")
list(APPEND cmd
"--cov=${CMAKE_CURRENT_SOURCE_DIR}"
"--cov-report=html:${coverage_directory}/coverage.html"
"--cov-report=xml:${coverage_directory}/coverage.xml"
)
if(pytest_cov_version VERSION_LESS "2.5.0")
message(WARNING
"Test coverage will be produced, but will not contain branch coverage information, "
"because the pytest extension 'cov' does not support it "
"(need 2.5.0, found '${pytest_cov_version}').")
else()
list(APPEND cmd "--cov-branch")
endif()
list(APPEND ARG_ENV "COVERAGE_FILE=${coverage_directory}/.coverage")
endif()
endif()
if(ARG_ENV)
set(ARG_ENV "ENV" ${ARG_ENV})
endif()
if(ARG_APPEND_ENV)
set(ARG_APPEND_ENV "APPEND_ENV" ${ARG_APPEND_ENV})
endif()
if(ARG_APPEND_LIBRARY_DIRS)
set(ARG_APPEND_LIBRARY_DIRS "APPEND_LIBRARY_DIRS" ${ARG_APPEND_LIBRARY_DIRS})
endif()
if(ARG_RUNNER)
set(ARG_RUNNER "RUNNER" ${ARG_RUNNER})
endif()
if(ARG_TIMEOUT)
set(ARG_TIMEOUT "TIMEOUT" "${ARG_TIMEOUT}")
endif()
if(ARG_WORKING_DIRECTORY)
set(ARG_WORKING_DIRECTORY "WORKING_DIRECTORY" "${ARG_WORKING_DIRECTORY}")
endif()
if(ARG_SKIP_TEST)
set(ARG_SKIP_TEST "SKIP_TEST")
endif()
ament_add_test(
"${testname}"
COMMAND ${cmd}
OUTPUT_FILE "${CMAKE_BINARY_DIR}/ament_cmake_pytest/${testname}.txt"
RESULT_FILE "${result_file}"
${ARG_RUNNER}
${ARG_SKIP_TEST}
${ARG_ENV}
${ARG_APPEND_ENV}
${ARG_APPEND_LIBRARY_DIRS}
${ARG_TIMEOUT}
${ARG_WORKING_DIRECTORY}
)
set_tests_properties(
"${testname}"
PROPERTIES
LABELS "pytest"
)
endfunction()
|