2017-04-19 56 views
10

如何在CMake上为我的Android本机C++代码设置GoogleTest? Android NDK附带googletest,但说明仅适用于Android.mk(here)。如何将Android.mk gtest安装程序移植到我的CMakeLists.txt中?一旦设置完成,是否可以通过Android Studio的测试配置运行测试运行器?GoogleTest for Android NDK C++与CMake

回答

1

我只能提供对您的第一个和主要问题的答案,但它是一个可行的解决方案。这不是特定于Android的;只要您可以运行CMake和CTest,它就会工作。

我不知道很多关于GoogleTest,但我记得有一个几个月前,一个非常类似的问题。就我而言,我想用CMake和Boost UnitTestFramework。

我搜索了一下,然后我遇到了a certain tutorial。他们提供的解决方案仅仅是使用正则表达式解析测试文件的内容。好处是,它是可定制的,并允许每个文件进行多个单元测试。我做到了这一点,它工作得非常好。当然,当你添加新的单元测试时,你必须重新运行CMake。

就像我说的,我会在下面发布是针对升压UnitTestFramework,但最大的区别是在正则表达式和变量名我使用。如果你不习惯在CMake中使用正则表达式(我不是),here是关于字符串操作的官方文档页面。

这里是CMakeLists.txt文件我结束了。我使用这个作为独立的CMakeLists.txt文件在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() 

适合我。一个build/目录下运行CMake的,运行所有测试产量后:

$ 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 

希望使用正则表达式不会导致你two problems :)。

+0

@ user740857此答案有用吗?如果是,请随时接受并/或奖励赏金。如果不是,你能否简要解释一下为什么其他人有机会为你提供更好的答案? –

+0

非常感谢您的见解。我似乎仍然无法理解如何从您的信息转到Android设置。 – user740857

+0

@ user740857是的,这是真的,我给你一个相当复杂的解决方案。但我不认为有没有简单的方法可以在不编写CMake代码的情况下将GoogleTest移植到CMake。 –