CTest

Overview

CTest는 cmake로 구성한 빌드환경에  빌드 및 테스트를 수행하고 그 결과를 dashboard에 게재할 수 있도록 도와준다.

cmake에 대해서는 아래 링크를 참조한다.

Hello World for CTest

대규모 프로젝트의 빌드환경 구성은 아래처럼 만드는 경우가 많다.
[lib] 폴더에는 library 빌드 구성이 되어 있고 [src] 폴더는 library를 이용하는 application 빌드 환경이 있을 것 이다. 그리고 [test] 폴더에는 library 등을 테스트할 수 있는 application이 있다.
[test] 폴더의 application은 cunit , cppunit 또는 googletest 와 같은 unit test framework을 이용하여 작성할 수 있다. CTest는 어떤 unit test framework를 사용하는지 상관하지 않는다.
다만, test application이 return 0(main 함수가 return 0)하면 PASS로 판단하고 그 이외는 FAIL 처리한다.

프로젝트 폴더구성

├── CMakeLists.txt (1)
├── [lib]
│   ├── CMakeLists.txt (2)
│   ├── utility.cpp
│   └── utility.h
├── [src]
│   ├── CMakeLists.txt (3)
│   └── main.cpp
└── [test]
    ├── CMakeLists.txt (4)
    └── test.cpp

CMakeLists.txt(1)
  • include(CTest) script를 추가하여 CTest  cmake module를 include하도록 한다.
  • add_test(<test name> <executable file>) 추가하여 테스트수행할 실행화일을 설정한다.
  • 아래 예제는 동일한 test_hello  프로그램을 test-1, 2 , 3이름으로 테스트를 수행하도록 하였다.
  • <executable file> 실행파일은 어떠한 unit test framework를 사용해도 상관없다. 다만 return 0 으로 application이 종료하면 PASS, 그 이외는 FAIL로 처리된다.

cmake_minimum_required(VERSION 2.8)
project(hello_ctest)

add_subdirectory(lib)
add_subdirectory(src)
add_subdirectory(test)

include (CTest)
add_test(test-1 test/test_hello)
add_test(test-2 test/test_hello)
add_test(test-3 test/test_hello)

[lib] 폴더 내용

CMakeLists.txt(2)

cmake_minimum_required(VERSION 2.8)
project(utility)

add_library(utility SHARED utility.cpp)

utility.cpp

#include "utility.h"

int g_value = 0;

void setValue(int value)
{
 g_value = value;
}

int getValue(void)
{
 return g_value;
}

[src] 폴더 내용

CMakeLists.txt(3)

cmake_minimum_required(VERSION 2.8)
project(hello_application)

include_directories(../lib)
add_executable(hello main.cpp)

add_dependencies(hello utility)
target_link_libraries(hello utility)

main.cpp

#include <stdio.h>
#include "utility.h"

int main(int argc, char* argv[])
{
 printf("previous: %d\n", getValue());
 setValue(1000);
 printf("after   : %d\n", getValue());

 return 0;
}

[test] 폴더 내용

CMakeLists.txt(4)

cmake_minimum_required(VERSION 2.8)
project(unit_test)

include_directories(../lib)
add_executable(test_hello test.cpp)

add_dependencies(test_hello utility)
target_link_libraries(test_hello utility)

test.cpp

  • xunit 을 이용하여 unit test를 작성한다. 본 예제는 그냥 printf 출력하는 예제이다.
#include <stdio.h>
#include "utility.h"

int main(int argc, char* argv[])
{
 setValue(1000);
 printf("evaluate value: %d\n", getValue());

 return 0;
}

Hello CTest 실행결과

  • cmake
mhkang2@mhkang2dev ~/Dropbox/samples/make/ctest $ cmake .
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mhkang2/Dropbox/samples/make/ctest

  • make
mhkang2@mhkang2dev ~/Dropbox/samples/make/ctest $ make
Scanning dependencies of target utility
[ 16%] Building CXX object lib/CMakeFiles/utility.dir/utility.cpp.o
[ 33%] Linking CXX shared library libutility.so
[ 33%] Built target utility
Scanning dependencies of target hello
[ 50%] Building CXX object src/CMakeFiles/hello.dir/main.cpp.o
[ 66%] Linking CXX executable hello
[ 66%] Built target hello
Scanning dependencies of target test_hello
[ 83%] Building CXX object test/CMakeFiles/test_hello.dir/test.cpp.o
[100%] Linking CXX executable test_hello
[100%] Built target test_hello

  • ctest
mhkang2@mhkang2dev ~/Dropbox/samples/make/ctest $ ctest
Test project /home/mhkang2/Dropbox/samples/make/ctest
    Start 1: test-1
1/3 Test #1: test-1 ...........................   Passed    0.00 sec
    Start 2: test-2
2/3 Test #2: test-2 ...........................   Passed    0.00 sec
    Start 3: test-3
3/3 Test #3: test-3 ...........................   Passed    0.00 sec

100% tests passed, 0 tests failed out of 3

Total Test time (real) =   0.01 sec


CDash

CTest는 빌드 및 테스트 결과를 dashboard에 report 하는 기능이 제공하여 Web으로 그 결과를 확인할 수 있다.
my.cdash.org 사이트에서 dashboard를  유/무료로 제공하여 CTest 결과를 Web으로 조회할 수 있다. 이 사이트에 가입(무료)하여 "hello ctest" 라는 프로젝트를 생성하였다. 아래에서 작성한 예제는 my.cdash.org 사이트의 "hello ctest" 라는 프로젝트에 어떻게 보고하는지 보여주고 있다.

해야하는 일은 단 한가지다. CMakeLists.txt (1) 파일이 존재하는 최 상위 폴더에 CTestConfig.cmake 파일을 추가하면 모든 것이 끝난다.

CTestConfig.cmake

set(CTEST_PROJECT_NAME "hello ctest")
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "my.cdash.org")
set(CTEST_DROP_LOCATION "/submit.php?project=hello+ctest")
set(CTEST_DROP_SITE_CDASH TRUE)

  • CTEST_DROP_METHOD
    • The value may be cp, ftp, http, https, scp, or xmlrpc.

cmake .

mhkang2@mhkang2dev ~/Dropbox/samples/make/ctest $ cmake .
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mhkang2/Dropbox/samples/make/ctest

ctest -D Experimental

위 ctest 가 수행될 때 내부적으로 make가 호출되어 전체 빌드가 된다.
ctest 실행하기 전에 make를 미리 호출해버리면 빌드 정보(warn/error) 정보가 모두 0 으로 보고될 수 있다. 따라서 ctest 호출은 한번도 make를 호출하지 않은 상태에서 하도록 한다.
mhkang2@mhkang2dev ~/Dropbox/samples/make/ctest $ ctest -D Experimental
   Site: mhkang2dev
   Build name: Linux-c++
Create new tag: 20171206-0714 - Experimental
Configure project
   Each . represents 1024 bytes of output
    . Size of output: 0K
Build project
   Each symbol represents 1024 bytes of output.
   '!' represents an error and '*' a warning.
    . Size of output: 1K
   0 Compiler errors
   0 Compiler warnings
Test project /home/mhkang2/Dropbox/samples/make/ctest
    Start 1: test-1
1/3 Test #1: test-1 ...........................   Passed    0.00 sec
    Start 2: test-2
2/3 Test #2: test-2 ...........................   Passed    0.00 sec
    Start 3: test-3
3/3 Test #3: test-3 ...........................   Passed    0.00 sec

100% tests passed, 0 tests failed out of 3

Total Test time (real) =   0.00 sec
Performing coverage
 Cannot find any coverage files. Ignoring Coverage request.
Submit files (using http)
   Using HTTP submit method
   Drop site:http://my.cdash.org/submit.php?project=hello+ctest
   Uploaded: /home/mhkang2/Dropbox/samples/make/ctest/Testing/20171206-0714/Build.xml
   Uploaded: /home/mhkang2/Dropbox/samples/make/ctest/Testing/20171206-0714/Configure.xml
   Uploaded: /home/mhkang2/Dropbox/samples/make/ctest/Testing/20171206-0714/Test.xml
   Submission successful
빌드 및 테스트 결과 파일 Build.xml, Configure.xml, Test.xml 가 my.cdash.org에 http post명령으로 upload되고 있다.
cdash.org 말고 다른 dashboard와 연동도 가능할 것으로 보인다.

cdash.org 조회 화면

위 예제가 정상으로 동작하면 아래와 같은 Web화면으로 빌드/테스트 결과 내용을 볼 수 있다.
아래 테이블에 표시된 숫자를 누르면 상세한 정보를 확인할 수 있다.


References

  • https://cmake.org/cmake/help/v3.0/module/CTest.html
  • https://www.cdash.org/

댓글