CMakeとCTest:make testはテストをビルドしません


88

make testターゲットを使用してテストの一部を自動的に実行するために、CMakeでCTestを試しています。問題は、CMakeがプロジェクトの一部であるため、実行するテストをビルドする必要があることをCMakeが「理解」しないことです。

だから私はこの依存関係を明示的に指定する方法を探しています。

回答:


78

それは間違いなくCMakeのバグ(以前に追跡ここでは、これは箱から出して動作しないこと)。回避策は次のとおりです。

add_test(TestName ExeName)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}
                  DEPENDS ExeName)

その後make check、実行すると、テストがコンパイルおよび実行されます。複数のテストがある場合DEPENDS exe1 exe2 exe3 ...は、上記の行で使用する必要があります。


1
add_custom_targetコマンドで別のターゲット名を選択する必要があるように見えるので、「make test」ターゲットは未使用のままになると思いますか?
claf 2009

うん。「テストの作成」と「チェックの作成」の唯一の違いは、前者は「テストの実行中...」を最初に表示し、ビルドの依存関係をチェックしないことです。
richq 2009

2
@rq-しかし、複数のプロジェクトでこれを行うには(1つのCMakeLists.txtが他のサブプロジェクトである場合)、それぞれがcheckターゲットを定義し、それらが衝突する可能性がある
Artyom

2
@Artyom-その場合、同等の「すべてをテストする」だけを使用した方がよいでしょう。実際、これは私がとにかくやっていることです。
richq

4
実際には、「make test」を実行して、最初に再ビルドを行わずにテストをそのまま実行できるcmakeの機能(バグではない)と
考える人もい

53

実際に使用する方法がありますmake test。テスト実行可能ファイルのビルドをテストの1つとして定義し、テスト間の依存関係を追加する必要があります。あれは:

ADD_TEST(ctest_build_test_code
         "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target test_code)
ADD_TEST(ctest_run_test_code test_code)
SET_TESTS_PROPERTIES(ctest_run_test_code
                     PROPERTIES DEPENDS ctest_build_test_code)

11
これはスケールアップする唯一のものであり、テストを実行するために「すべて作成」ターゲットをビルドするように強制するものではありません。考えられる欠点:バイナリのビルドエラーの詳細は、生成されたLastTest.logファイルにのみ表示され、stdout / stderrには表示されない
Dave Abrahams

2
いい答えだ!ただし、ビルドターゲットに構成を追加する必要があります。そうしないと、すべての構成でテストを実行することができません。add_test(NAME "$ {ARGV0} _BUILD" COMMAND "$ {CMAKE_COMMAND}" --build $ {CMAKE_BINARY_DIR} --target $ {target} "--config" "$ <CONFIG>")
Daniel

1
これは、多くの偽のテストでテストレポーターを詰まらせます。

CMake> = 3.7を使用している場合、推奨されるアプローチはフィクスチャを使用することです。以下の私の答えを参照しください。
John Freeman、

13

richqの答えの変形を使用します。トップレベルにCMakeLists.txtbuild_and_testすべてのテストを構築および実行するためのカスタムターゲットを追加します。

find_package(GTest)
if (GTEST_FOUND)
    enable_testing()
    add_custom_target(build_and_test ${CMAKE_CTEST_COMMAND} -V)
    add_subdirectory(test)
endif()

のさまざまなサブプロジェクトCMakeLists.txtファイルにtest/、各テスト実行可能ファイルをの依存関係として追加しますbuild_and_test

include_directories(${CMAKE_SOURCE_DIR}/src/proj1)
include_directories(${GTEST_INCLUDE_DIRS})
add_executable(proj1_test proj1_test.cpp)
target_link_libraries(proj1_test ${GTEST_BOTH_LIBRARIES} pthread)
add_test(proj1_test proj1_test)
add_dependencies(build_and_test proj1_test)

このアプローチでは、私はする必要があります make build_and_test代わりにmake test(またはmake all test)を実行するだけで済み、テストコード(およびその依存関係)のみをビルドできるという利点があります。ターゲット名が使えないのは残念testです。私の場合、cmakeandを呼び出してからツリー外のデバッグおよびリリース(およびクロスコンパイル)ビルドを実行するトップレベルのスクリプトがありmake、それがに変換testされるため、それほど悪くはありませんbuild_and_test

明らかに、GTestのものは必要ありません。私はたまたまGoogle Testを使用していて、CMake / CTestでそれを使用する完全な例を共有したいと思っていました。私見、このアプローチには、使用を許可するという利点もありますctest -V、テストの実行中にGoogleテストの出力を表示するます。

1: Running main() from gtest_main.cc
1: [==========] Running 1 test from 1 test case.
1: [----------] Global test environment set-up.
1: [----------] 1 test from proj1
1: [ RUN      ] proj1.dummy
1: [       OK ] proj1.dummy (0 ms)
1: [----------] 1 test from proj1 (1 ms total)
1:
1: [----------] Global test environment tear-down
1: [==========] 1 test from 1 test case ran. (1 ms total)
1: [  PASSED  ] 1 test.
1/2 Test #1: proj1_test .......................   Passed    0.03 sec

この例では、ctestの代わりにctest -Vが実行することをmake testに取得する方法はありますか?ctestの出力は非常に不完全に見え、単一のテストがあると表示されます。
Rajiv

6

あなたがエミュレートしようとしているならmake check、あなたはこのwikiエントリが役に立つかもしれません:

http://www.cmake.org/Wiki/CMakeEmulateMakeCheck

私はちょうどそれが成功すると言っていることを確認しました(CMake 2.8.10)。


1
これにより、実行時にすべての実行可能ファイルがビルドされますmake check。コンパイル時間が支配的なテストの場合、これはctest -R役に立たなくなります。
usr1234567 2015

4

頭痛の種を省いてください:

make all test

そのまま使用でき、テストを実行する前に依存関係を構築します。これがいかに単純かを考えるとmake test、コードが壊れていても最後のコンパイルテストを実行するオプションを提供するので、ネイティブ機能はほとんど便利になります。


1
CDashでは機能しません。make all && ctestを呼び出す必要があります。そうすると、建物はアップロードされたテストの一部ではなくなります。そのため、ビルドの警告やエラーは表示されません。
usr1234567 2015

2
また、2つは並行して実行されるため、並行ビルドが必要な場合はうまく機能しませんmake -j4 all && make test。また、Make以外のビルドツールを使用すると不安定になります。
poolie

4

CMake> = 3.7を使用している場合、推奨されるアプローチはフィクスチャを使用することです:

add_executable(test test.cpp)
add_test(test_build
  "${CMAKE_COMMAND}"
  --build "${CMAKE_BINARY_DIR}"
  --config "$<CONFIG>"
  --target test
)
set_tests_properties(test_build PROPERTIES FIXTURES_SETUP    test_fixture)
add_test(test test)
set_tests_properties(test       PROPERTIES FIXTURES_REQUIRED test_fixture)

これは次のことを行います。

  • testビルドされた実行可能なターゲットを追加しますtest.cpp
  • test_buildCmakeを実行してターゲットをビルドする「テスト」を追加しますtest
  • マーク test_buildテストをフィクスチャのセットアップタスクとしてますtest_fixture
  • 実行可能ファイルを実行testするだけのテストを追加しtestます
  • testテストにフィクスチャが必要であることをマークしtest_fixtureます。

したがって、テストtestが実行されるたびに、まずtest test_buildが実行され、必要な実行可能ファイルが作成されます。


$<CONFIG>が設定されていない場合--target、はの引数になり--configます。
loshad vtapkah

$<CONFIG>は常に空でないと信じています。これは構成名のジェネレーター式です:cmake.org/cmake/help/latest/manual/…違いがないので、とにかく引用符で囲むように回答を編集します。
John Freeman、

どうやって走るのcmake?私はこのようにしていますmkdir build; cd build; cmake ..; make。そして、CMAKE_BUILD_TYPE手動で設定するまで、デフォルトはなく、関連するすべての変数は空のようです。(現在Debian 10では他のプラットフォームをチェックしていませんでした)
loshad vtapkah '30

1

これは私が打ち出して使用してきたものです:

set(${PROJECT_NAME}_TESTS a b c)

enable_testing()
add_custom_target(all_tests)
foreach(test ${${PROJECT_NAME}_TESTS})
        add_executable(${test} EXCLUDE_FROM_ALL ${test}.cc)
        add_test(NAME ${test} COMMAND $<TARGET_FILE:${test}>)
        add_dependencies(all_tests ${test})
endforeach(test)

build_command(CTEST_CUSTOM_PRE_TEST TARGET all_tests)
string(CONFIGURE \"@CTEST_CUSTOM_PRE_TEST@\" CTEST_CUSTOM_PRE_TEST_QUOTED ESCAPE_QUOTES)
file(WRITE "${CMAKE_BINARY_DIR}/CTestCustom.cmake" "set(CTEST_CUSTOM_PRE_TEST ${CTEST_CUSTOM_PRE_TEST_QUOTED})" "\n")

YMMV


0

デリックの回答、簡略化してコメント:

# It is impossible to make target "test" depend on "all":
# https://gitlab.kitware.com/cmake/cmake/-/issues/8774
# Set a magic variable in a magic file that tells ctest
# to invoke the generator once before running the tests:
file(WRITE "${CMAKE_BINARY_DIR}/CTestCustom.cmake"
    "set(CTEST_CUSTOM_PRE_TEST ${CMAKE_MAKE_PROGRAM})\n"
)

ninja all test誰かがそうした場合に備えて、を実行することの同時実行性の問題を解決しないため、これは完全に正しくはありません。逆に、今、あなたは2つの忍者プロセスを持っているからです。

究極の解決策は、私に尋ねれば、CMakeの代わりにMesonを使用することです。Mesonは多くのことの中でとりわけこれを正しくしています。


-3

上記の答えはすべて完璧です。しかし、実際にはCMakeはテストツールとしてCTestを使用しているため、ミッションを実行する標準的な方法(そうだと思います)は次のとおりです。

enable_testing ()
add_test (TestName TestCommand)
add_test (TestName2 AnotherTestCommand)

次に、cmakeを実行してmakeを実行し、ターゲットをビルドします。その後、make testを実行するか、単に実行することができます

ctest

あなたは結果を得るでしょう。これはCMake 2.8でテストされています。

詳細はhttp://cmake.org/Wiki/CMake/Testing_With_CTest#Simple_Testingで確認してください。


5
実際に実行されているテストに必要なターゲットのみを構築したい場合があるため、反対票を投じました。
デイブアブラハムズ

12
この答えは質問を誤解しているようだ:CTEST、使用:OPは既にこの答えは推奨していたとおりにやっているenable_testing()add_test()問題は彼が手動テストを実行する前に、ビルドコマンドを発行しなければならないことである、など。彼は、make testターゲットが必要に応じてテスト実行可能ファイルを自動的にビルドすることを望んでいます。
bames53 2014年

-4

すべての回答は良いですが、コマンドによるテストを実行するという伝統の違反を意味しますmake test。私はこのトリックを行いました:

add_test(NAME <mytest>
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMAND sh -c "make <mytarget>; $<TARGET_FILE:<mytarget>>")

これは、テストが実行可能なターゲットのビルド(オプション)と実行で構成されることを意味します。


6
:-Dルール#1:shなしでシステムを使用しないでください。そのようなシステムを知っていますか?
dyomas 2014

11
はい、Windowsはその1つです。
David Faure

3
これもハードコードされてmakeおり、他のビルドツール用のスクリプトを生成するCMakeの機能を失っています。
poolie
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.