Skip to content

Commit

Permalink
Merge pull request #16 from asmodehn/pytest
Browse files Browse the repository at this point in the history
adding pytest as a test runner.
  • Loading branch information
asmodehn committed Jun 2, 2016
2 parents 8676228 + 5bbb4de commit 1a0158b
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ catkin_package(
catkin-pip-setup.cmake
catkin-pip-prefix.cmake
catkin-pip-requirements.cmake
test/pytest.cmake
test/nosetests.cmake
)

# to be found in devel space
Expand Down
4 changes: 4 additions & 0 deletions cmake/catkin-pip-fixups.req
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@

# Upgrading to use latest nose
nose
# Also install pytest since we support it
pytest
pytest-cov
pytest-timeout

# Fixing security since python 2.7.6 on trusty is broken : https://stackoverflow.com/questions/29099404/ssl-insecureplatform-error-when-using-requests-package
# On trusty it seems that installing libgnutls28-dev fixes the issue...
Expand Down
10 changes: 9 additions & 1 deletion cmake/catkin-pip-prefix.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,20 @@ macro(catkin_pip_setup_prefix ws_prefix)

# Providing another catkin nosetests usage...
# now we can finally use the simple "nosetests" entry_point (forcing cmake to find it)
find_program( PIP_NOSETESTS NAMES nosetests PATHS ${ws_prefix}/@CATKIN_GLOBAL_BIN_DESTINATION@ NO_DEFAULT_PATH)
find_program( PIP_NOSETESTS NAMES "nosetests" "nosetests-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}" PATHS ${ws_prefix}/@CATKIN_GLOBAL_BIN_DESTINATION@ NO_DEFAULT_PATH)
if(PIP_NOSETESTS)
message( STATUS "Found catkin_pip nosetests command at ${PIP_NOSETESTS}.")
else()
message( FATAL_ERROR "catkin_pip nosetests command not found in ${ws_prefix}/@CATKIN_GLOBAL_BIN_DESTINATION@. Make sure you have installed the nose pip package on your ${ws_prefix} workspace.")
endif()

# Same for py.test
find_program( PIP_PYTEST NAMES "py.test" "py.test-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}" PATHS ${ws_prefix}/@CATKIN_GLOBAL_BIN_DESTINATION@ NO_DEFAULT_PATH)
if(PIP_PYTEST)
message( STATUS "Found catkin_pip py.test command at ${PIP_PYTEST}.")
else()
message( FATAL_ERROR "catkin_pip py.test command not found in ${ws_prefix}/@CATKIN_GLOBAL_BIN_DESTINATION@. Make sure you have installed the pytest pip package on your ${ws_prefix} workspace.")
endif()

endif()
endmacro()
4 changes: 2 additions & 2 deletions cmake/catkin-pip.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ message(STATUS "Loading catkin-pip.cmake from ${CMAKE_CURRENT_LIST_DIR}... ")
# protecting against missing cmake file dependency
include ( "${CMAKE_CURRENT_LIST_DIR}/catkin-pip-requirements.cmake" RESULT_VARIABLE CATKIN_PIP_REQUIREMENTS_FOUND )
IF ( NOT CATKIN_PIP_REQUIREMENTS_FOUND )
message ( FATAL_ERROR "{CMAKE_CURRENT_LIST_DIR}/catkin-pip-requirements.cmake Not Found !!!" )
message ( FATAL_ERROR "${CMAKE_CURRENT_LIST_DIR}/catkin-pip-requirements.cmake Not Found !!!" )
ENDIF ( NOT CATKIN_PIP_REQUIREMENTS_FOUND )

# protecting against missing cmake file dependency
include ( "${CMAKE_CURRENT_LIST_DIR}/catkin-pip-setup.cmake" RESULT_VARIABLE CATKIN_PIP_SETUP_FOUND )
IF ( NOT CATKIN_PIP_SETUP_FOUND )
message ( FATAL_ERROR "{CMAKE_CURRENT_LIST_DIR}/catkin-pip-setup.cmake Not Found !!!" )
message ( FATAL_ERROR "${CMAKE_CURRENT_LIST_DIR}/catkin-pip-setup.cmake Not Found !!!" )
ENDIF ( NOT CATKIN_PIP_SETUP_FOUND )

catkin_add_env_hooks(42.site-packages SHELLS bash DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../env-hooks)
Expand Down
120 changes: 120 additions & 0 deletions cmake/test/nosetests.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
_generate_function_if_testing_is_disabled("catkin_add_nosetests")

#
# Add Python nose tests.
#
# Nose collects tests from the directory ``dir`` automatically.
#
# .. note:: The test can be executed by calling ``nosetests``
# directly or using:
# `` make run_tests_${PROJECT_NAME}_nosetests_${dir}``
# (where slashes in the ``dir`` are replaced with periods)
#
# :param path: a relative or absolute directory to search for
# nosetests in or a relative or absolute file containing tests
# :type path: string
# :param DEPENDENCIES: the targets which must be built before executing
# the test
# :type DEPENDENCIES: list of strings
# :param TIMEOUT: the timeout for individual tests in seconds
# (default: 60)
# :type TIMEOUT: integer
# :param WORKING_DIRECTORY: the working directory when executing the
# tests (this option can only be used when the ``path`` argument is a
# file but not when it is a directory)
# :type WORKING_DIRECTORY: string
#
# @public
#
function(catkin_add_nosetests path)
_warn_if_skip_testing("catkin_add_nosetests")

if(NOT PIP_NOSETESTS)
message(STATUS "skipping nosetests(${path}) in project '${PROJECT_NAME}'")
return()
endif()

cmake_parse_arguments(_nose "" "TIMEOUT;WORKING_DIRECTORY" "DEPENDENCIES" ${ARGN})
if(NOT _nose_TIMEOUT)
set(_nose_TIMEOUT 60)
endif()
if(NOT _nose_TIMEOUT GREATER 0)
message(FATAL_ERROR "nosetests() TIMEOUT argument must be a valid number of seconds greater than zero")
endif()

# check that the directory exists
set(_path_name _path_name-NOTFOUND)
if(IS_ABSOLUTE ${path})
set(_path_name ${path})
else()
find_file(_path_name ${path}
PATHS ${CMAKE_CURRENT_SOURCE_DIR}
NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
if(NOT _path_name)
message(FATAL_ERROR "Can't find nosetests path '${path}'")
endif()
endif()

# check if coverage reports are being requested
if("$ENV{CATKIN_TEST_COVERAGE}" STREQUAL "1")
set(_covarg " --with-coverage")
endif()

# strip PROJECT_SOURCE_DIR and PROJECT_BINARY_DIR prefix from output_file_name
set(output_file_name ${path})
_strip_path_prefix(output_file_name "${output_file_name}" "${PROJECT_SOURCE_DIR}")
_strip_path_prefix(output_file_name "${output_file_name}" "${PROJECT_BINARY_DIR}")
if("${output_file_name}" STREQUAL "")
set(output_file_name ".")
endif()
string(REPLACE "/" "." output_file_name ${output_file_name})
string(REPLACE ":" "." output_file_name ${output_file_name})

set(output_path ${CATKIN_TEST_RESULTS_DIR}/${PROJECT_NAME})
# make --xunit-file argument an absolute path (https://github.com/nose-devs/nose/issues/779)
get_filename_component(output_path "${output_path}" ABSOLUTE)
set(cmd "${CMAKE_COMMAND} -E make_directory ${output_path}")
if(IS_DIRECTORY ${_path_name})
set(tests "--where=${_path_name}")
else()
set(tests "${_path_name}")
endif()
set(cmd ${cmd} "${PIP_NOSETESTS} -P --process-timeout=${_nose_TIMEOUT} ${tests} --with-xunit --xunit-file=${output_path}/nosetests-${output_file_name}.xml${_covarg}")
catkin_run_tests_target("nosetests" ${output_file_name} "nosetests-${output_file_name}.xml" COMMAND ${cmd} DEPENDENCIES ${_nose_DEPENDENCIES} WORKING_DIRECTORY ${_nose_WORKING_DIRECTORY})
endfunction()

find_program(PIP_NOSETESTS NAMES
"nosetests${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}"
"nosetests-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}"
"nosetests${PYTHON_VERSION_MAJOR}"
"nosetests-${PYTHON_VERSION_MAJOR}"
"nosetests")
if(PIP_NOSETESTS)
message(STATUS "Using Python nosetests: ${PIP_NOSETESTS}")
else()
if("${PYTHON_VERSION_MAJOR}" STREQUAL "3")
message(WARNING "nosetests not found, Python tests can not be run (try installing package 'python3-nose')")
else()
message(WARNING "nosetests not found, Python tests can not be run (try installing package 'python-nose')")
endif()
endif()

macro(_strip_path_prefix var value prefix)
if("${value}" STREQUAL "${prefix}" OR "${value}" STREQUAL "${prefix}/")
set(${var} "")
else()
set(${var} "${value}")
string(LENGTH "${prefix}/" prefix_length)
string(LENGTH "${value}" var_length)
if(${var_length} GREATER ${prefix_length})
string(SUBSTRING "${value}" 0 ${prefix_length} var_prefix)
if("${var_prefix}" STREQUAL "${prefix}/")
# passing length -1 does not work for CMake < 2.8.5
# http://public.kitware.com/Bug/view.php?id=10740
string(LENGTH "${value}" _rest)
math(EXPR _rest "${_rest} - ${prefix_length}")
string(SUBSTRING "${value}" ${prefix_length} ${_rest} ${var})
endif()
endif()
endif()
endmacro()
101 changes: 101 additions & 0 deletions cmake/test/pytest.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
_generate_function_if_testing_is_disabled("catkin_add_pytests")

include ( "${CMAKE_CURRENT_LIST_DIR}/nosetests.cmake" RESULT_VARIABLE CATKIN_PIP_NOSETESTS_FOUND )
IF ( NOT CATKIN_PIP_NOSETESTS_FOUND )
message ( FATAL_ERROR "${CMAKE_CURRENT_LIST_DIR}/nosetests.cmake Not Found !!!" )
ENDIF ( NOT CATKIN_PIP_NOSETESTS_FOUND )

#
# Add Python pytest tests.
#
# Nose collects tests from the directory ``dir`` automatically.
#
# .. note:: The test can be executed by calling ``py.test``
# directly or using:
# `` make run_tests_${PROJECT_NAME}_pytests_${dir}``
# (where slashes in the ``dir`` are replaced with periods)
#
# :param path: a relative or absolute directory to search for
# pytests in or a relative or absolute file containing tests
# :type path: string
# :param DEPENDENCIES: the targets which must be built before executing
# the test
# :type DEPENDENCIES: list of strings
# :param TIMEOUT: the timeout for individual tests in seconds
# (default: 60)
# :type TIMEOUT: integer
# :param WORKING_DIRECTORY: the working directory when executing the
# tests (this option can only be used when the ``path`` argument is a
# file but not when it is a directory)
# :type WORKING_DIRECTORY: string
#
# @public
#
function(catkin_add_pytests path)
_warn_if_skip_testing("catkin_add_pytests")

if(NOT PIP_PYTEST)
message(STATUS "skipping pytests(${path}) in project '${PROJECT_NAME}'")
return()
endif()

cmake_parse_arguments(_pytest "" "TIMEOUT;WORKING_DIRECTORY" "DEPENDENCIES" ${ARGN})
if(NOT _pytest_TIMEOUT)
set(_pytest_TIMEOUT 60)
endif()
if(NOT _pytest_TIMEOUT GREATER 0)
message(FATAL_ERROR "py.test() TIMEOUT argument must be a valid number of seconds greater than zero")
endif()

# check that the directory exists
set(_path_name _path_name-NOTFOUND)
if(IS_ABSOLUTE ${path})
set(_path_name ${path})
else()
find_file(_path_name ${path}
PATHS ${CMAKE_CURRENT_SOURCE_DIR}
NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
if(NOT _path_name)
message(FATAL_ERROR "Can't find pytests path '${path}'")
endif()
endif()

# check if coverage reports are being requested
if("$ENV{CATKIN_TEST_COVERAGE}" STREQUAL "1")
set(_covarg "--cov-report xml --cov-report annotate --cov=${PROJECT_SOURCE_DIR}")
endif()

# strip PROJECT_SOURCE_DIR and PROJECT_BINARY_DIR prefix from output_file_name
set(output_file_name ${path})
_strip_path_prefix(output_file_name "${output_file_name}" "${PROJECT_SOURCE_DIR}")
_strip_path_prefix(output_file_name "${output_file_name}" "${PROJECT_BINARY_DIR}")
if("${output_file_name}" STREQUAL "")
set(output_file_name ".")
endif()
string(REPLACE "/" "." output_file_name ${output_file_name})
string(REPLACE ":" "." output_file_name ${output_file_name})

set(output_path ${CATKIN_TEST_RESULTS_DIR}/${PROJECT_NAME})
# make --xunit-file argument an absolute path (https://github.com/nose-devs/nose/issues/779)
get_filename_component(output_path "${output_path}" ABSOLUTE)
set(cmd "${CMAKE_COMMAND} -E make_directory ${output_path}")
set(tests "${_path_name}")
set(cmd ${cmd} "${PY_TEST} --timeout=${_pytest_TIMEOUT} ${tests} --junit-xml ${output_path}/pytests-${output_file_name}.xml ${_covarg}")
catkin_run_tests_target("pytests" ${output_file_name} "pytests-${output_file_name}.xml" COMMAND ${cmd} DEPENDENCIES ${_pytest_DEPENDENCIES} WORKING_DIRECTORY ${_pytest_WORKING_DIRECTORY})
endfunction()

find_program(PY_TEST NAMES
"py.test${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}"
"py.test-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}"
"py.test${PYTHON_VERSION_MAJOR}"
"py.test-${PYTHON_VERSION_MAJOR}"
"py.test")
if(PY_TEST)
message(STATUS "Using Python py.test: ${PY_TEST}")
else()
if("${PYTHON_VERSION_MAJOR}" STREQUAL "3")
message(WARNING "py.test not found, Python tests can not be run (try installing package 'python3-pytest')")
else()
message(WARNING "py.test not found, Python tests can not be run (try installing package 'python-pytest')")
endif()
endif()
1 change: 1 addition & 0 deletions test/pipproject/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ catkin_package()
## Unit tests
if (CATKIN_ENABLE_TESTING)
catkin_add_nosetests(${PIP_PROJECT_DIR}/tests)
catkin_add_pytests(${PIP_PROJECT_DIR}/tests)
endif()

0 comments on commit 1a0158b

Please sign in to comment.