Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

C++ のユニットテストをいい感じにする

More than 5 years have passed since last update.

C++ のユニットテストを簡単にあつかえるようにしてみた。
要素としては次。

  • Google Test
  • CMake
    • http://www.cmake.org/
    • ユニットテストのコンパイルを楽にするために。
    • 実行と結果の要約表示は付属の CTest を使うといい感じになる。

ここでは CMake まわりの設定について説明していく。
Google Test の使い方については各自で調べてください。

サンプル

CMake の都合上ディレクトリー構造がキモになってくるのでわかりやすさのためにサンプル作ってみた。

https://github.com/januswel/ctest-gtest

トップで次のコマンドを打つとテストまで完了する。

mkdir build
cd build
cmake ..
make
ctest

ディレクトリー構造は次のようにしている。

project root/
    cmake/                  # CMake 用設定置き場
    include/                # C++ 用ヘッダーファイル置き場
    lib/                    # ライブラリー用ディレクトリー
        CMakeLists.txt      # ライブラリー用設定ファイル
        util/               # ライブラリー そのいち
        ...                 # その他のライブラリー
    test/                   # テスト用ディレクトリー
        CMakeLists.txt      # テスト用設定ファイル
        awesome/            # テスト そのいち
        ...                 # その他の機能群用のディレクトリー
    CMakeLists.txt          # ビルド用設定ファイル
    main.cpp                # 実行ファイル用ソース

トップの CMakeLists.txt の次の部分がテストに関する設定。

https://github.com/januswel/ctest-gtest/blob/master/CMakeLists.txt

# tests
if(NOT without-test)
    enable_testing()
    include(cmake/gtest.cmake)
    add_subdirectory(test)
endif()

CMake の条件分岐

ここではテストのコンパイルをやめるかどうかを制御するために使っている。普段はテストこみでコンパイル、事情があるときだけ外す、という形。

make 時に変数 without-test が定義されているかどうかで判別している。
条件分岐については次参照。

http://qiita.com/janus_wel/items/adb2f9f9623a1fde0860

CTest を有効化する

enable_testing() で有効になる。

その上で次のコマンドでテストの設定をする。

https://github.com/januswel/ctest-gtest/blob/master/test/awesome/CMakeLists.txt

  • add_test()
    • ctest コマンド実行時にテスト対象に含める実行ファイルを指定する。
    • add_executable の TARGET_FILE を指定しておいたりする。
  • set_property()
    • テストにラベルをつけて、特定のラベルのついたテストのみ実行ということができる。
    • set_tests_properties() でもつけられるけど紛らわしいのでおすすめしない。
cmake_minimum_required(VERSION 2.8)

add_executable(awesome-test main.cpp)
target_link_libraries(awesome-test
    gtest
    gtest_main
    pthread
    util
    )

add_test(
    NAME awesome
    COMMAND $<TARGET_FILE:awesome-test>
    )

# run with: ctest -L lib
set_property(
    TEST awesome
    PROPERTY LABELS lib awesome
    )

上記のようにしておくと次のコマンドのいずれかでこのテストが走る。
make test はラベル指定時が煩雑だね。

  • ctest
  • ctest -L lib
  • make test
  • ARGS="-L lib" make test

CMake で外部プロジェクトを取り込む

CMake には ExternalProject というモジュールが付属していて、リモートの CMake プロジェクトを取り込めるようになっている。

http://www.cmake.org/cmake/help/v3.0/module/ExternalProject.html

Google Test は ExternalProject で読み込めるようになっている。
次のような設定をファイルに切り出しておくと使い回しがきく。

https://github.com/januswel/ctest-gtest/blob/master/cmake/gtest.cmake

gtest.cmake
cmake_minimum_required(VERSION 2.8)

# Google Test settings
include(ExternalProject)

ExternalProject_Add(
    GoogleTest
    URL https://googletest.googlecode.com/files/gtest-1.7.0.zip
    PREFIX ${CMAKE_CURRENT_BINARY_DIR}/lib
    INSTALL_COMMAND ""
    LOG_DOWNLOAD ON
    )

ExternalProject_Get_Property(GoogleTest source_dir)
include_directories(${source_dir}/include)

ExternalProject_Get_Property(GoogleTest binary_dir)
add_library(gtest STATIC IMPORTED)
set_property(
    TARGET gtest
    PROPERTY IMPORTED_LOCATION ${binary_dir}/libgtest.a
    )
add_library(gtest_main STATIC IMPORTED)
set_property(
    TARGET gtest_main
    PROPERTY IMPORTED_LOCATION ${binary_dir}/libgtest_main.a
    )

実際に使う場合は include(gtest.cmake) という感じで。

テストを作る場合

test ディレクトリー以下に追加していく。
機能や関数ごとにサブディレクトリーを作って追加していくのがいい。
サブディレクトリーを追加した場合は test/CMakeLists.txt にそのディレクトリーを add_subdirectory() するのを忘れないように。

あと include ディレクトリーを include_directories() しているので、ヘッダーファイルのパスを include 直下からのものにする。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away