概要
C++でAndroid向けにビルドしたライブラリを、AndroidStudioとGoogle Testを使ってテストする方法をまとめます。
方法
Android向けC++ライブラリ作成
Android用ライブラリの作成方法は別の記事にまとめました。
https://qiita.com/Wagomu056/items/c21ba1c428e9574defbc
テスト実行用プロジェクトの作成
プロジェクトを作成します。
「Empty Activity」で作成しました。
CMake設定
CMakeLists.txtを追加
app/src/androidTest に、cppディレクトリを作成します。
そのディレクトリにCMakeLists.txtを追加します。
CMakeLists.txt
cmake_minimum_required(VERSION 3.10.2)
project("native-lib-tests")
# --------------------
# Google Test
# --------------------
# Add Google Test directory
set(GOOGLETEST_DIR ${ANDROID_NDK}/sources/third_party/googletest)
# Add Google Test sources
add_library(gtest STATIC
${GOOGLETEST_DIR}/src/gtest_main.cc
${GOOGLETEST_DIR}/src/gtest-all.cc)
# Set include directories
target_include_directories(gtest PRIVATE
${GOOGLETEST_DIR})
target_include_directories(gtest PUBLIC
${GOOGLETEST_DIR}/include)
# --------------------
# Add test executable
# --------------------
add_executable(native-lib-tests test.cpp)
target_link_libraries(native-lib-tests gtest)
# Change output path to app/.cxx/Debug/output
set_target_properties(native-lib-tests PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/../../output"
)
gtestはNDKに含まれているものを使います。
また、「RUNTIME_OUTPUT_DIRECTORY」で実行ファイルを分かりやすいパスに出力するよう変更しています。
build.gradleにCMakeLists.txtを読み込むように設定
app/src/build.gradleに以下を追加します。
abiFiltersにはテストを実行する端末のアーキテクチャを設定します。
android {
testOptions {
unitTests {
externalNativeBuild {
cmake {
path "src/androidTest/cpp/CMakeLists.txt"
}
}
defaultConfig {
ndk {
abiFilters "arm64-v8a"
}
}
}
}
}
テストコードの追加
app/src/androidTest/cpp に、テストコードを追加します。
まずはテストが実行されるかを確認するためのコードです。
#include <gtest/gtest.h>
TEST(ExampleTest, BasicAssertion) {
EXPECT_EQ(1, 1);
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
テスト実行
この状態でビルドすると、app/.cxx/Debug/outputに実行ファイルnative-lib-testsが出力されます。
これをadbで実機にコピーして、実行権限をつけて実行します。
adb push "app/.cxx/Debug/output/native-lib-tests" /data/local/tmp
adb shell "chmod 755 /data/local/tmp/native-lib-tests && \
/data/local/tmp/native-lib-tests"
実行前にエミュレータを起動しておくか、実機を繋いでおく必要があります。
以下のようにファイルが転送・実行されて成功すると思います。
app/.cxx/Debug/output/native-lib-tests: 1 file pushed, 0 skipped. 111.4 MB/s (7193864 bytes in 0.062s)
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from ExampleTest
[ RUN ] ExampleTest.BasicAssertion
[ OK ] ExampleTest.BasicAssertion (0 ms)
[----------] 1 test from ExampleTest (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[ PASSED ] 1 test.
ライブラリの追加
テストを実行できるのが確認できたので、ライブラリを追加します。
いつも通り、ファイルを追加してCMakeLists.txtに追加します。
ライブラリファイル追加
Android向けにビルドしたライブラリとヘッダファイルをapp/libs以下に追加します。
app/libs
├── include
│ └── ndk_library.h
└── libndk_lib.a
CMakeLists.txtに追加
追加したライブラリをCMakeLists.txtに追記します。
IMPORTEDとして追加します。
# --------------------
# Libs
# --------------------
set(APP_ROOT ${CMAKE_SOURCE_DIR}/../../..)
add_library(ndk_lib STATIC IMPORTED)
set_target_properties(ndk_lib PROPERTIES
IMPORTED_LOCATION ${APP_ROOT}/libs/libndk_lib.a
INTERFACE_INCLUDE_DIRECTORIES ${APP_ROOT}/libs/include)
ライブラリをリンクするよう追記します。
target_link_libraries(native-lib-tests gtest ndk_lib)
Testを追加
テストファイルにライブラリのテストを追記します。
#include <ndk_library.h>
...
TEST(ExampleTest, NDKLibTest) {
EXPECT_EQ(ndk_lib_add(2, 2), 4);
}
実行
テストを追加したので、2つのテストが実行されます。
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from ExampleTest
[ RUN ] ExampleTest.BasicAssertion
[ OK ] ExampleTest.BasicAssertion (0 ms)
[ RUN ] ExampleTest.NDKLibTest
[ OK ] ExampleTest.NDKLibTest (0 ms)
[----------] 2 tests from ExampleTest (0 ms total)
まとめ
以上でAndroid向けライブラリをGoogle Testで実行できるようになりました。
最終的なCMakeLists.txtとtest.cppを書いておきます。
CMakeLists.txtとtest.cpp
cmake_minimum_required(VERSION 3.10.2)
project("native-lib-tests")
# --------------------
# Google Test
# --------------------
# Add Google Test directory
set(GOOGLETEST_DIR ${ANDROID_NDK}/sources/third_party/googletest)
# Add Google Test sources
add_library(gtest STATIC
${GOOGLETEST_DIR}/src/gtest_main.cc
${GOOGLETEST_DIR}/src/gtest-all.cc)
# Set include directories
target_include_directories(gtest PRIVATE
${GOOGLETEST_DIR})
target_include_directories(gtest PUBLIC
${GOOGLETEST_DIR}/include)
# --------------------
# Libs
# --------------------
set(APP_ROOT ${CMAKE_SOURCE_DIR}/../../..)
add_library(ndk_lib STATIC IMPORTED)
set_target_properties(ndk_lib PROPERTIES
IMPORTED_LOCATION ${APP_ROOT}/libs/libndk_lib.a
INTERFACE_INCLUDE_DIRECTORIES ${APP_ROOT}/libs/include)
# --------------------
# Add test executable
# --------------------
add_executable(native-lib-tests test.cpp)
target_link_libraries(native-lib-tests gtest ndk_lib)
# Change output path to app/.cxx/Debug/output
set_target_properties(native-lib-tests PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/../../output"
)
#include <gtest/gtest.h>
#include <ndk_library.h>
TEST(ExampleTest, BasicAssertion) {
EXPECT_EQ(1, 1);
}
TEST(ExampleTest, NDKLibTest) {
EXPECT_EQ(ndk_lib_add(2, 2), 4);
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
これから
もしテストに必要なモジュールがある場合、build.gradleに追加すればいいのでしょうか?
今後、分かりましたら追記しようと思います。
参考元