GoogleTest para Android NDK C++ con CMake
android-ndk (1)
Solo puedo brindar una respuesta a su primera y principal pregunta, pero es una solución que funciona. No es específico de Android; funciona siempre que pueda ejecutar CMake y CTest.
No sé mucho sobre GoogleTest, pero recuerdo haber tenido una pregunta muy similar hace unos meses. En mi caso, quería usar CMake con Boost UnitTestFramework.
Lo busqué un poco, luego me encontré con cierto tutorial . La solución que proporcionaron fue simplemente analizar el contenido de los archivos de prueba con una expresión regular. Lo bueno es que es bastante personalizable y permite varias pruebas unitarias por archivo. Hice esto, y funcionó bastante bien. Tienes que volver a ejecutar CMake cuando añadas nuevas pruebas unitarias, por supuesto.
Como dije, lo que publicaré a continuación es para Boost UnitTestFramework, pero las mayores diferencias se encuentran en las expresiones regulares y los nombres de variables que uso. En caso de que no esté acostumbrado a usar expresiones regulares con CMake (no lo soy), aquí hay una página de documentación oficial sobre operaciones de cadenas.
Aquí está el archivo CMakeLists.txt
el que terminé. Lo usé como un archivo independiente CMakeLists.txt
debajo de un directorio de test/
.
# =============================
# = ADDING TESTS =
# =============================
include(CTest)
find_package(Boost COMPONENTS unit_test_framework REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
file(GLOB_RECURSE TEST_SRCS RELATIVE ${TEST_SOURCE_DIR} *.cpp)
set(TEST_EXTRA_LIBS ${Boost_LIBRARIES} ${TEST_MAIN_LIB})
# Function which, given a file name and a test name, yields the
# name of the GoogleTest test case.
# That way, several different files can have the same test name.
# Adapt this to GoogleTest.
function(getTestCase testFileName testName outTestCase)
string(REGEX MATCH "Test([_a-zA-Z][_a-zA-Z0-9]*)" match ${testFileName})
string(REGEX REPLACE ".*Test([_a-zA-Z][_a-zA-Z0-9]*).*" "//1" testCase ${match})
set(testCase Test${testCase}${testName})
set(${outTestCase} ${testCase} PARENT_SCOPE)
endfunction()
# Function which adds all tests within a certain test file.
function(add_all_tests_in testSrc)
get_filename_component(testFileName ${testSrc} NAME_WE)
add_executable(${testFileName} ${testSrc})
target_link_libraries(${testFileName} ${TEST_EXTRA_LIBS})
set_target_properties(${testFileName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
file(READ "${testSrc}" testFileContents)
# You should change this Regex for what you need in your case.
# Maybe something like:
# "TEST//( *([_a-zA-Z][_a-zA-Z0-9]* *, *[_a-zA-Z][_a-zA-Z0-9]*) *//)"
string(REGEX MATCHALL "DEF_TEST_CASE//( *([_a-zA-Z][_a-zA-Z0-9]*) *//)" unitTests ${testFileContents})
foreach(match ${unitTests})
# This replace will also probably need some change.
string(REGEX REPLACE ".*//( *([_a-zA-Z][_a-zA-Z0-9]*) *//).*" "//1" testName ${match})
getTestCase(${testFileName} ${testName} testCase)
# Actually add the test.
# I wanted my CTest test names to be in the form
# <fileName>.<testName>, but you can use any
# format you want. Suit yourself.
#
# Also, in order for CMake to run the tests one by one,
# you have to find how to invoke the test executable.
# In the case of Boost, the option --run_test=<Boost_Test_Name>
# runs only the test called <Boost_Test_Name>. There should be
# an equivalent option for GoogleTest, I''m sure.
add_test(NAME "${testFileName}.${testName}" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${testFileName} --run_test=${testCase} --catch_system_error=yes)
endforeach()
endfunction()
# Actually add all tests in all test files.
foreach(testSrc ${TEST_SRCS})
add_all_tests_in(${testSrc})
endforeach()
Funciona para mi. Después de ejecutar CMake bajo un directorio build/
, ejecutando todas las pruebas rinde:
$ cd test && ctest
Test project /home/anthonyd973/Git/Git_Projects/MySweeper/build/test
Start 1: TestFieldMaker.makeFromFile
1/12 Test #1: TestFieldMaker.makeFromFile ........ Passed 0.03 sec
Start 2: TestFieldMaker.make
2/12 Test #2: TestFieldMaker.make ................ Passed 0.01 sec
Start 3: TestFieldMaker._computeFieldDims
3/12 Test #3: TestFieldMaker._computeFieldDims ... Passed 0.01 sec
Start 4: TestFieldMaker._populateField
4/12 Test #4: TestFieldMaker._populateField ...... Passed 0.00 sec
Start 5: TestInputField.InputField
5/12 Test #5: TestInputField.InputField .......... Passed 0.00 sec
Start 6: TestCell.Cell
6/12 Test #6: TestCell.Cell ...................... Passed 0.00 sec
Start 7: TestCell.initNeighbours
7/12 Test #7: TestCell.initNeighbours ............ Passed 0.00 sec
Start 8: TestCell.updateNeighbours
8/12 Test #8: TestCell.updateNeighbours .......... Passed 0.00 sec
Start 9: TestCell._mark
9/12 Test #9: TestCell._mark ..................... Passed 0.00 sec
Start 10: TestMySweeper.MySweeper
10/12 Test #10: TestMySweeper.MySweeper ............ Passed 0.00 sec
Start 11: TestField.Field
11/12 Test #11: TestField.Field .................... Passed 0.01 sec
Start 12: TestField._initNeighbours
12/12 Test #12: TestField._initNeighbours .......... Passed 0.00 sec
100% tests passed, 0 tests failed out of 12
Total Test time (real) = 0.10 sec
Con suerte, usar expresiones regulares no te causa dos problemas :).
¿Cómo configuro GoogleTest para mi código C ++ nativo en Android con CMake? El Android NDK viene incluido con googletest, pero las instrucciones solo están disponibles para Android.mk ( aquí ). ¿Cómo transfiero la configuración de gtest de Android.mk a mi CMakeLists.txt? Y una vez configurada, ¿es posible ejecutar el corrector de prueba a través de las configuraciones de prueba de Android Studio?