CMake: Birim testleri ile proje yapısı


139

Projemi, üretim kaynaklarını ( srcalt klasörde) ve testleri (alt klasörde) içerecek şekilde yapılandırmaya çalışıyorum test. Bunu oluşturmak için CMake kullanıyorum. Minimal bir örnek olarak aşağıdaki dosyaları var:

CMakeLists.txt:

cmake_minimum_required (VERSION 2.8) 
project (TEST) 

add_subdirectory (src) 
add_subdirectory (test) 

src / CMakeLists.txt:

add_executable (demo main.cpp sqr.cpp) 

src / sqr.h

#ifndef SQR_H
#define SQR_H
double sqr(double);    
#endif // SQR_H

src / sqr.cpp

#include "sqr.h"
double sqr(double x) { return x*x; }

src / main.cpp - sqr kullanır, önemli değil

Test / CMakeLists.txt:

find_package(Boost COMPONENTS system filesystem unit_test_framework REQUIRED)

include_directories (${TEST_SOURCE_DIR}/src) 

ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK) 

add_executable (test test.cpp ${TEST_SOURCE_DIR}/src/sqr.cpp) 

target_link_libraries(test
                      ${Boost_FILESYSTEM_LIBRARY}
                      ${Boost_SYSTEM_LIBRARY}
                      ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
                      )

enable_testing()
add_test(MyTest test)

Test / test.cpp:

#define BOOST_TEST_MODULE SqrTests
#include <boost/test/unit_test.hpp>

#include "sqr.h"

BOOST_AUTO_TEST_CASE(FailTest)
{
    BOOST_CHECK_EQUAL(5, sqr(2));
}

BOOST_AUTO_TEST_CASE(PassTest)
{
    BOOST_CHECK_EQUAL(4, sqr(2));
}

Birkaç soru:

  1. Bu yapı mantıklı mı? Bu kodu yapılandırırken en iyi uygulamalar nelerdir? (C # ve java'dan geliyorum ve orada bir anlamda daha kolay)
  2. Dosyadaki srcklasördeki tüm dosyaları listelemem gerektiğinden hoşlanmıyorum test/CMakeLists.txt. Bu bir kütüphane projesi olsaydı, sadece kütüphaneyi bağlardım. Diğer projedeki tüm cpp dosyalarını listelemekten kaçınmanın bir yolu var mı?
  3. Çizgiler enable_testing()ve ne add_test(MyTest test)yapıyor? Hiç bir etki görmedim. CMake (veya CTest) testlerini nasıl çalıştırabilirim?
  4. Şimdiye kadar sadece cmake .kök klasörde koştum , ancak bu her yerde geçici dosyalarla bir karışıklık yarattı. Derleme sonuçlarını makul bir yapıda nasıl alabilirim?

Kendimi bir CMake acemi olarak görüyorum, bu yüzden kabul edilen en iyi uygulamaların ne olduğunu bilmiyorum, ama FWIW hem ana hem de testin bağlı olduğu bir "sqr" kütüphanesi * yapacağım. (* veya ahlaki eşdeğeri)
user786653

Yanıtlar:


125

Soru 1 ve 2 için, main.cpp (bu durumda sadece src / sqr.cpp ve src / sqr.h) dışındaki test dışı dosyalarınızdan bir kütüphane oluşturmanızı ve daha sonra listelemeyi (ve daha önemlisi) kaynakların iki kez yeniden derlenmesi).

3. soru için, bu komutlar çalıştırılabilir "test" inizi herhangi bir argüman olmadan çağıran "MyTest" adlı bir test ekler. Ancak, bu komutları üst düzey CMakeLists.txt'nize değil, test / CMakeLists.txt dosyasına eklediğiniz için, testi yalnızca oluşturma ağacınızın "test" alt dizininden başlatabilirsiniz (deneyin cd test && ctest -N). Testin üst düzey oluşturma dizininizden çalıştırılabilir olmasını istiyorsanız add_test, üst düzey CMakeLists.txt'den arama yapmanız gerekir . Bu ayrıca add_test, test exe'niz aynı CMakeLists.txt dosyasında tanımlanmadığı için daha ayrıntılı formunu kullanmanız gerektiği anlamına gelir.

Sizin durumunuzda, kök klasöründe cmake çalıştırdığınız için, yapı ağacınız ve kaynak ağacınız bir ve aynıdır. Bu kaynak içi bir yapı olarak bilinir ve ideal değildir, bu da 4. soruya götürür.

Yapı ağacını oluşturmak için tercih edilen yöntem, kaynak dışı bir yapı oluşturmak, yani kaynak ağacınızın dışında bir yerde bir dizin oluşturmak ve oradan cmake çalıştırmaktır. Projenizin kök dizininde bir "derleme" dizini oluşturmak ve yürütmek cmake ..bile kaynak ağacınıza müdahale etmeyen temiz bir yapı sağlayacaktır.

Son nokta çalıştırılabilir "test" (büyük / küçük harfe duyarlı) olarak adlandırmaktan kaçınmaktır. Nedeni için bu cevaba bakınız .

Bu değişiklikleri başarmak için aşağıdakileri yapardım:

CMakeLists.txt:

cmake_minimum_required (VERSION 2.8)
project (TEST)
add_subdirectory (src) 
add_subdirectory (test)
enable_testing ()
add_test (NAME MyTest COMMAND Test)


src / CMakeLists.txt:

add_library (Sqr sqr.cpp sqr.h)
add_executable (demo main.cpp)
target_link_libraries (demo Sqr)


Test / CMakeLists.txt:

find_package (Boost COMPONENTS system filesystem unit_test_framework REQUIRED)
include_directories (${TEST_SOURCE_DIR}/src
                     ${Boost_INCLUDE_DIRS}
                     )
add_definitions (-DBOOST_TEST_DYN_LINK)
add_executable (Test test.cpp)
target_link_libraries (Test
                       Sqr
                       ${Boost_FILESYSTEM_LIBRARY}
                       ${Boost_SYSTEM_LIBRARY}
                       ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
                       )

2
Sadece .h dosyalarını CMakeLists.txt dosyalarına da eklediğinizi fark ettim. Gerekli mi? Ve onları dışarıda bırakırsam ne olur?
Grzenio

3
@Grzenio Bu sadece bir kolaylık özelliğidir - IDE'lerde MSVC gibi hedefin bir parçası olarak görünürler, ancak aksi takdirde bunun bir etkisi yoktur.
Fraser

1
TEST_SOURCE_DIR nerede ayarlanır?
aggsol

6
Çağrılırken otomatik CMake tarafından ayarlanır project (TEST)bkz - cmake.org/cmake/help/v3.6/variable/PROJECT-NAME_SOURCE_DIR.html
Fraser

> hedefin bir parçası olarak IDE'lerde MSVC gibi görünüyorlar --- MSVC başlıklı dizini "dizin ekle" olarak işaretlemeyi desteklemiyor mu?
isnullxbh

46

@Fraser örneğini seviyorum ancak test / CMakeLists.txt dosyasında add_test komutunu ve add_subdirectory (test) öncesinde enable_testing komutunu kullanırdım.

Bu şekilde testlerinizi test / CMakeLists.txt dosyasında belirtirken testlerinizi en üst düzey derleme dizininden çalıştırabilirsiniz.

Sonuç şöyle görünecektir (@Fraser örneğini tekrar kullandım):

CMakeLists.txt

cmake_minimum_required (VERSION 2.8)
project (TEST)
add_subdirectory (src)

enable_testing ()
add_subdirectory (test)

src / CMakeLists.txt

add_library (Sqr sqr.cpp sqr.h)
add_executable (demo main.cpp)
target_link_libraries (demo Sqr)

Test / CMakeLists.txt

find_package (Boost COMPONENTS system filesystem unit_test_framework REQUIRED)
include_directories (${TEST_SOURCE_DIR}/src
                     ${Boost_INCLUDE_DIRS}
                     )
add_definitions (-DBOOST_TEST_DYN_LINK)
add_executable (Test test.cpp)
target_link_libraries (Test
                       Sqr
                       ${Boost_FILESYSTEM_LIBRARY}
                       ${Boost_SYSTEM_LIBRARY}
                       ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
                       )
add_test (NAME MyTest COMMAND Test)

1
Teşekkürler, ctest -Nalt dizini eklemeden önce testi etkinleştirme ipucuna kadar hiçbir test göstermedim .
alaferg

@alaferg: aksi takdirde derleme dizinindeki test alt dizinine ulaşırlar.
gauteh

4
Keşke CMake'in yapıya benzeyen bir şeyi olsaydı.
ruipacheco
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.