c++ - Pruebas de falla de construcción esperadas en CMake
automated-tests ctest (2)
La respuesta de WILL_FAIL
es un buen enfoque, en particular, la propiedad WILL_FAIL
es un buen consejo. Sin embargo, hay una alternativa a hacer que el objetivo fracasado forme parte del proyecto principal. El caso de uso en la pregunta es para lo que está destinado el modo ctest --build-and-test
. En lugar de hacer que el objetivo esperado a fallar sea parte de la compilación principal, puede colocarlo en su propio mini proyecto separado, que luego se construye como parte de una prueba. Un ejemplo de cómo podría verse esto en el proyecto principal es algo como esto:
add_test(NAME iter_conversion
COMMAND ${CMAKE_CTEST_COMMAND}
--build-and-test
${CMAKE_CURRENT_LIST_DIR}/test_iter
${CMAKE_CURRENT_BINARY_DIR}/test_iter
--build-generator ${CMAKE_GENERATOR}
--test-command ${CMAKE_CTEST_COMMAND}
)
set_tests_properties(iter_conversion PROPERTIES WILL_FAIL TRUE)
Esto tiene la ventaja de que formará parte de los resultados de las pruebas del proyecto y, por lo tanto, será más probable que se ejecuten regularmente como parte de los procesos de prueba normales. En el ejemplo anterior, el directorio test_iter
es esencialmente su propio proyecto separado. Si necesita pasarle información desde la compilación principal, puede hacerlo agregando --build-options
para definir las variables de caché para pasar a su ejecución CMake. Verifique los últimos documentos para obtener ayuda corregida / aclarada recientemente en esta área.
A veces es bueno comprobar que ciertas cosas no se pueden construir, por ejemplo:
// Next line should fail to compile: can''t convert const iterator to iterator.
my_new_container_type::iterator it = my_new_container_type::const_iterator();
¿Es posible incorporar este tipo de cosas en CMake / CTest? Estoy buscando algo como esto en CMakeLists.txt
:
add_build_failure_executable(
test_iterator_conversion_build_failure
iterator_conversion_build_failure.cpp)
add_build_failure_test(
test_iterator_conversion_build_failure
test_iterator_conversion_build_failure)
(Por supuesto, estas directivas específicas de CMake no existen, por lo que sé.)
Puedes hacer esto más o menos como lo describiste. Puede agregar un destino que no se compile, luego agregar una prueba que invoque a cmake --build
para intentar construir el objetivo. Todo lo que queda es establecer la propiedad de prueba WILL_FAIL
en true.
Entonces, digamos que tiene sus pruebas en un archivo llamado "will_fail.cpp" que contiene:
#if defined TEST1
non-compiling code for test 1
#elif defined TEST2
non-compiling code for test 2
#endif
Entonces puedes tener algo como lo siguiente en tu CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project(Example)
include(CTest)
# Add a couple of failing-to-compile targets
add_executable(will_fail will_fail.cpp)
add_executable(will_fail_again will_fail.cpp)
# Avoid building these targets normally
set_target_properties(will_fail will_fail_again PROPERTIES
EXCLUDE_FROM_ALL TRUE
EXCLUDE_FROM_DEFAULT_BUILD TRUE)
# Provide a PP definition to target the appropriate part of
# "will_fail.cpp", or provide separate files per test.
target_compile_definitions(will_fail PRIVATE TEST1)
target_compile_definitions(will_fail_again PRIVATE TEST2)
# Add the tests. These invoke "cmake --build ..." which is a
# cross-platform way of building the given target.
add_test(NAME Test1
COMMAND ${CMAKE_COMMAND} --build . --target will_fail --config $<CONFIGURATION>
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME Test2
COMMAND ${CMAKE_COMMAND} --build . --target will_fail_again --config $<CONFIGURATION>
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# Expect these tests to fail (i.e. cmake --build should return
# a non-zero value)
set_tests_properties(Test1 Test2 PROPERTIES WILL_FAIL TRUE)
Obviamente, puedes envolver todo esto en una función o macro si tienes muchos de estos para escribir.