CMake & CTest: Make test test oluşturmaz


91

make testHedef kullanarak bazı testlerimi otomatik olarak çalıştırmak için CMake'de CTest'i deniyorum . Sorun şu ki CMake, yürütmek istediğim testin projenin bir parçası olduğu için inşa edilmesi gerektiğini "anlamıyor".

Bu nedenle, bu bağımlılığı açıkça belirtmenin bir yolunu arıyorum.

Yanıtlar:


81

Öyle tartışmalı bir CMake hatasından (daha önce izlenen burada bu kutunun dışında çalışmıyor). Çözüm aşağıdakileri yapmaktır:

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

Sonra çalıştırabilirsiniz make checkve testi derleyip çalıştıracaktır. Birkaç testiniz varsa DEPENDS exe1 exe2 exe3 ..., yukarıdaki satırda kullanmanız gerekir .


1
bu yüzden, add_custom_target komutunda farklı bir hedef adı seçmeniz gerektiğinden "test yap" hedefinin kullanılmadan kalacağını tahmin ediyorum?
claf

Evet. "Test yap" ve "kontrol yap" arasındaki tek fark, ilk önce "Test çalıştırılıyor ..." şovlarıdır ve herhangi bir yapı bağımlılığını kontrol etmez.
richq

2
@rq - ancak bunu birden fazla projeyle nasıl yapabilirim (bir CMakeLists.txt diğerinin alt projesi olduğunda) böylece her biri checkhedefi tanımlar ve çarpışabilirler
Artyom

2
@Artyom - bu durumda muhtemelen eşdeğer "tümünü test et" seçeneğini kullanmaktan daha iyisiniz. Aslında, zaten yaptığım şey bu.
richq

4
Aslında, bazıları bunu bir cmake özelliği (hata değil) olarak, "test yap" çalıştırabileceğiniz ve önce herhangi bir yeniden
derleme

55

Aslında kullanmanın bir yolu var make test. Test yürütülebilir yapısını testlerden biri olarak tanımlamanız ve ardından testler arasına bağımlılıklar eklemeniz gerekir. Yani:

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
Bu, ölçeği artıran ve yalnızca testi çalıştırmak için sizi "tümünü yap" hedefleri oluşturmaya zorlamayan tek hedeftir. Olası bir dezavantaj: İkililerdeki derleme hatalarının ayrıntıları yalnızca oluşturulan LastTest.log dosyasında görünüyor ve stdout / stderr'de gösterilmiyor
Dave Abrahams

2
İyi cevap! Yapılandırmayı yapı hedefine eklemelisiniz. Aksi takdirde testleri tüm konfigürasyonlarda çalıştırmak mümkün değildir. add_test (NAME "$ {ARGV0} _BUILD" COMMAND "$ {CMAKE_COMMAND}" --build $ {CMAKE_BINARY_DIR} --target $ {target} "--config" "$ <CONFIG>")
Daniel

1
Bu, test muhabirini bir dizi sahte testle tıkar.

CMake> = 3.7 kullanıyorsanız, önerilen yaklaşım armatürleri kullanmaktır. Bkz cevabımı altında.
John Freeman

13

Richq'in cevabının bir varyantını kullanıyorum. En üst düzeyde CMakeLists.txt, build_and_testtüm testleri oluşturmak ve çalıştırmak için özel bir hedef ekliyorum :

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

Aşağıdaki çeşitli alt proje CMakeLists.txtdosyalarında test/, her bir test yürütülebilir dosyasını aşağıdakilere bağımlı olarak ekliyorum 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)

Bu yaklaşımla, (veya ) make build_and_testyerine yapmam gerekiyor ve yalnızca test kodu (ve bağımlılıkları) oluşturma avantajına sahip. Hedef adını kullanamamam çok yazık . Ben dışı ağacının hata ayıklama ve sürüm (ve çapraz derlenmiş) çağırarak kurar yapan bir üst düzey komut dosyası var çünkü Benim durumumda, o kadar kötü değil sonra ve ve o çevirir içine .make testmake all testtestcmakemaketestbuild_and_test

Açıkçası, en iyi şeyler gerekli değil. Google Test kullanıyorum / beğeniyorum ve bunu CMake / CTest ile kullanmanın eksiksiz bir örneğini paylaşmak istedim. IMHO, bu yaklaşım aynı zamanda ctest -Vtestler çalıştırılırken Google Test çıktısını gösteren kullanmama izin verme avantajına da sahiptir :

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

Bu örnekte, ctest yerine ctest -V'nin yaptığını yapmak için test yapmanın bir yolu var mı? Ctest çıktısı çok eksik görünüyor ve sadece tek bir test olduğunu söylüyor.
Rajiv

6

Taklit etmeye çalışıyorsanız make check, bu wiki girişini yararlı bulabilirsiniz:

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

Dediğini başarılı bir şekilde yaptığını kontrol ettim (CMake 2.8.10).


1
Bu, çalışırken tüm çalıştırılabilir dosyaları oluşturacaktır make check. Baskın derleme sürelerine sahip testler için bu, ctest -Rişe yaramaz hale getirir .
usr1234567

4

Kendinizi baş ağrısından kurtarın:

make all test

Benim için kutudan çıktığı gibi çalışıyor ve testi çalıştırmadan önce bağımlılıklar oluşturacak. Bunun ne kadar basit olduğu göz önüne alındığında make test, kodunuz bozuk olsa bile size son derleme testlerini çalıştırma seçeneği sunduğu için yerel işlevselliği neredeyse kullanışlı hale getirir .


1
CDash ile çalışmaz. Make all && ctest'i aramanız gerekir ve bu durumda bina yüklenen testin bir parçası olmaz. Bu yüzden inşa uyarıları veya hataları görünmez.
usr1234567

2
Paralel bir yapı istiyorsanız, ikisi paralel çalışacağından, iyi çalışmaz: ihtiyacınız var make -j4 all && make test. Ayrıca, Make olmayan bir oluşturma aracı kullanıldığında da bozuluyor.
poolie

4

CMake> = 3.7 kullanıyorsanız, önerilen yaklaşım armatürleri kullanmaktır :

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)

Bu, aşağıdakileri yapar:

  • Oluşturulan testyürütülebilir bir hedef eklertest.cpp
  • test_buildHedef oluşturmak için Cmake çalıştıran bir "test" eklertest
  • Marks test_buildTest fikstür kurulum görevi olmaktest_fixture
  • testYalnızca testyürütülebilir dosyayı çalıştıran bir test ekleyin
  • testFikstür gerekmesi için testi işaretler test_fixture.

Bu nedenle, test her testçalıştırıldığında, önce test_buildgerekli yürütülebilir dosyayı oluşturan testi çalıştırır.


Eğer $<CONFIG>ayarlı değil --targetargümanı haline gelecektir --config.
loshad vtapkah

Her $<CONFIG>zaman boş olmadığına inanıyorum . Yapılandırma adı için bir üreteç ifadesidir: cmake.org/cmake/help/latest/manual/… Yanıtı tırnak içine alacak şekilde düzenleyeceğim çünkü hiçbir fark yaratmıyor .
John Freeman

Nasıl çalıştırabilirim cmake? Bu şekilde yapın: mkdir build; cd build; cmake ..; make. Ve CMAKE_BUILD_TYPEel ile ayarlanıncaya kadar herhangi bir varsayılan yok ve ilgili tüm değişkenler boş görünüyor . (şu anda Debian 10'da, diğer platformları kontrol etmedim)
loshad vtapkah

1

Bu benim çıkardığım ve kullandığım şey:

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

Derrick'in cevabı basitleştirilmiş ve yorumlanmıştır:

# 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"
)

Herhangi biri bunu yaparsa, koşmanın eşzamanlılık problemini çözmediği için tamamen doğru değildir ninja all test. Aksine, çünkü artık iki ninja süreciniz var.

(Ftr, ben de bu çözümü burada paylaştım .)


-3

Yukarıdaki tüm cevaplar mükemmel. Ama aslında CMake test araçları olarak CTest'i kullanıyor, bu nedenle görevi yerine getirmenin standart yöntemi (bence öyle):

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

O zaman kaç cmake ve yapmak hedefleri inşa etmek. Bundan sonra, test yap veya sadece çalıştırabilirsiniz

ctest

sonucu alacaksın. Bu CMake 2.8 altında test edilmiştir.

Ayrıntıları şu adreste kontrol edin: http://cmake.org/Wiki/CMake/Testing_With_CTest#Simple_Testing


5
Olumsuz oy verildi çünkü bazen yalnızca gerçekten çalıştırılan testler için gereken hedefleri oluşturmak istersiniz.
Dave Abrahams

12
Bu cevap soruyu yanlış görünüyor: CTest, kullanma: OP zaten bu cevabı önerir aynen yapıyor enable_testing(), add_test()sorun o elle testleri yapmaya öncesinde inşa komut vermeyi olmasıdır vb. make testHedefin gerektiğinde test yürütülebilir dosyalarını otomatik olarak oluşturmasını ister .
bames53

-4

Tüm cevaplar iyidir, ancak komuta göre bir test çalıştırma geleneğinin ihlal edildiğini gösterir make test. Bu numarayı yaptım:

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

Bu, testin yürütülebilir hedef oluşturmayı (isteğe bağlı olarak) ve çalıştırmayı içerdiği anlamına gelir.


6
:-D Kural # 1: sh olmadan sistemi kullanmayın. Böyle bir sistemi biliyor musunuz?
dyomas

11
Evet, Windows bunlardan biridir.
David Faure

3
Bu aynı zamanda CMake'nin makediğer derleme araçları için komut dosyaları oluşturma özelliğini de içerir ve kaybeder.
poolie
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.