このブログ記事では、CMakeでテストをセットアップする方法ついて紹介します。

信頼性の高いプロジェクトを構築するためには、さまざまな入力に対して機能が正しく動作するかを確認するテストを設定する必要があります。 CMakeにはテスト用のいくつかのツールが用意されており、本記事ではそれらを紹介します。
セットアップ
通常、tests
ディレクトリを設定し、テストを行いたい各機能のテスト用サブディレクトリを格納します。
各テストサブディレクトリには、通常tester
と名付けられるテスト用のソースコードと、
テスト用の実行ファイルをビルドするためのCMakeLists.txt
ファイルを含めます。
以下は、カスタムGraph
ライブラリを使用した例のファイル構造です。
このライブラリは隣接リストとグラフ探索アルゴリズム(BFSとDFS)を実装しています。
本記事の目的は、BFSとDFSが正しく動作するかをテストすることです。
CMakeLists.txt
main.cc
Graph
tests/
├── CMakeLists.txt
├── bfs/
│ ├── CMakeLists.txt
│ └── tester.cc
├── dfs/
│ ├── CMakeLists.txt
│ └── tester.cc
以下のトップレベルのCMakeLists.txt
では、BFSおよび/またはDFSをテストするオプションを定義し、tests
サブディレクトリを含めるか、
または実行ファイルmain.cc
のみをビルドするかを選択できるようにしています。
cmake_minimum_required(VERSION 3.31)
project(Project VERSION 1.0)
option(TEST_BFS "Testing BFS" ON)
option(TEST_DFS "Testing DFS" ON)
add_subdirectory(Graph)
if(TEST_BFS OR TEST_DFS)
add_subdirectory(tests)
endif()
if(NOT (TEST_BFS OR TEST_DFS))
add_executable(${PROJECT_NAME} main.cc)
target_link_libraries(${PROJECT_NAME} Graph)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/Graph/include)
endif()
Graph
ライブラリはテストとメインソースコードの両方で使用することを想定しているため、オプションを確認する前にGraph
サブディレクトリを含めます。
このセットアップにより、テストに関連するロジックを他のディレクトリから分離することができます。
CTest
CMakeにはテストプログラムのCTestが含まれており、これを使って簡単にテストを設定・実行できます。使用するには、
tests
ディレクトリ内のCMakeLists.txt
にenable_testing()
を追加してテストを有効化し、
add_test
を使用してテストケースを設定します。以下の例をご覧ください。
cmake_minimum_required(VERSION 3.31)
enable_testing()
if(TEST_BFS)
add_subdirectory(bfs)
add_test(NAME "BFS_TEST1" COMMAND bfs_test 2 6 0 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_test(NAME "BFS_TEST2" COMMAND bfs_test 0 4 1 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif()
if(TEST_DFS)
add_subdirectory(dfs)
add_test(NAME "DFS_TEST1" COMMAND dfs_test 2 6 0 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_test(NAME "DFS_TEST2" COMMAND dfs_test 0 4 1 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif()
ここで、bfs_test
とdfs_test
は実行ファイルの名前であり、開始ノード、ターゲットノード、および開始ノードからターゲットノードへのパスが存在するかどうかを受け取ります。
BFSとDFSは、ターゲットノードが開始ノードから到達可能かどうかを正しく判断する必要があります。テストが0を返す場合、CTestは成功として分類し、
それ以外の場合は失敗と見なします。以下にbfs_test
にコンパイルされるBFS用のtester.cc
の例を示します。
#include <AdjacencyList.h>
#include <GraphSearch.h>
#include <stdlib.h>
using namespace GraphSearch;
int main(int argc, char* argv[]) {
AdjacencyList g1(5);
g1.addEdge(0, 1);
g1.addEdge(0, 2);
g1.addEdge(1, 3);
g1.addEdge(2, 4);
int node1 = atoi(argv[1]);
int node2 = atoi(argv[2]);
int expectedResult = atoi(argv[3]);
return (expectedResult == BFS(g1, node1, node2));
}
ここでは、文字列を整数に変換する<stdlib.h>
のatoi
を使用しています。上記のtester.cc
は、
必要なGraph
ライブラリをリンクし、インクルードディレクトリの場所を指定する通常のCMakeLists.txt
でビルドできます。
プロジェクトはcmake -S . -B build/
およびビルドディレクトリ内でのmake
を使用してビルドされ、
ビルドディレクトリ内にtests
ディレクトリが作成されます。
build/tests
ディレクトリに移動してctest -N
を実行すると、設定したすべてのテストの一覧が表示され、
それをctest -VV
で実行できます。正しい実装がGraph
に提供されていれば、上記のテストは成功するはずです。
テストは、cmake
呼び出し時に-DTEST_BFS=OFF
および-DTEST_DFS=OFF
を含めることで簡単に無効化できます。
その後、ビルドディレクトリ内で./Project
を実行できます。
CDash
CTestを使用して、機能が開発環境で正しく動作することを確認できますが、他の環境でテストを実行する他のユーザーの結果を追跡し、 機能が正しくセットアップされていることを確認したい場合があります。CDashは、これを実現するためのダッシュボードを提供するオープンソースプロジェクトです。 CDashを使用するには独自のCDashサーバーをセットアップするか、CDashの公式ウェブサイトを利用できます。
CDashのダッシュボードでアカウントを登録した後、プロジェクト名、説明、リポジトリの場所など必要な情報を入力して新しいプロジェクトを作成できます。
プロジェクト作成後、プロジェクトセクションのその他のセクションに移動し、CTestConfig.cmake
を確認します。これをコピーして、
プロジェクトディレクトリ内にCTestConfig.cmake
を作成します。
リモートリポジトリに変更をプッシュした後、CMakeLists.txt
でtests
サブディレクトリを追加した後にinclude(CTest)
を含め、
プロジェクトをビルドします。その後、build/tests
内でctest -D Experimental
を実行すると、ダッシュボードでテスト結果が更新されているのを確認できます。
興味があれば、記事の末尾に引用されているCDashの動画を視聴し、公式ドキュメントを確認することをお勧めします。
結論
この記事では、CTestを使用したテストのセットアップと実行方法を説明し、CDashを簡単に紹介しました。CDashにはリモートリポジトリが必要ですが、 これは別の記事で取り上げます。CMakeに関する一連の記事が、プロジェクト構築の基本を理解する助けになったことを願っています。
リソース
- Code, Tech, and Tutorials. 2023. CMake Tutorial EP 13 | CTest. YouTube.
- Code, Tech, and Tutorials. 2024. CMake Tutorial EP 14 | CDash. YouTube.