[모던 CMake] 테스트 설정과 CI/CD 파이프라인 연동

모던 CMake를 활용하여 효율적인 C++ 프로젝트 빌드 시스템을 구축하는 방법을 계속해서 알아보겠습니다. 이번 글에서는 CMake를 활용한 테스트 설정CI/CD 파이프라인에 연동하는 방법에 대해 다루겠습니다.

CMake와 테스트 프레임워크

소프트웨어 품질을 높이기 위해서는 단위 테스트(Unit Test)가 필수적입니다. CMake는 테스트를 지원하기 위한 모듈과 명령어를 제공하며, 다양한 테스트 프레임워크와 쉽게 연동할 수 있습니다.

CTest 소개

CTest는 CMake에 내장된 테스트 러너로, 테스트를 실행하고 결과를 보고하는 기능을 제공합니다.

  • enable_testing(): 테스트를 활성화합니다.
  • add_test(): 테스트를 등록합니다.

Google Test와 CMake 연동

Google Test는 C++에서 널리 사용되는 단위 테스트 프레임워크입니다. FetchContent를 사용하여 프로젝트에 포함하고 CMake로 빌드할 수 있습니다.

FetchContent를 사용한 Google Test 포함

include(FetchContent)

FetchContent_Declare(
  googletest
  URL https://github.com/google/googletest/archive/release-1.11.0.zip
)

# 빌드 옵션 설정 (옵션)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)

FetchContent_MakeAvailable(googletest)

테스트 타겟 추가

enable_testing()

add_executable(MyTests tests/test.cpp)

target_link_libraries(MyTests PRIVATE MyLib gtest_main)

add_test(NAME MyTest COMMAND MyTests)
  • enable_testing(): 테스트 기능을 활성화합니다.
  • add_executable(MyTests tests/test.cpp): 테스트 실행 파일을 생성합니다.
  • target_link_libraries(MyTests PRIVATE MyLib gtest_main): 테스트 타겟에 라이브러리와 Google Test를 링크합니다.
  • add_test(): 테스트를 등록하여 ctest로 실행할 수 있게 합니다.

예제 디렉토리 구조

my_project/
├── CMakeLists.txt
├── src/
│   ├── CMakeLists.txt
│   └── mylib.cpp
├── include/
│   └── mylib.h
└── tests/
    ├── CMakeLists.txt
    └── test.cpp

최상위 CMakeLists.txt

cmake_minimum_required(VERSION 3.15)
project(MyProject)

add_subdirectory(src)
add_subdirectory(tests)

tests/CMakeLists.txt

include(FetchContent)

FetchContent_Declare(
  googletest
  URL https://github.com/google/googletest/archive/release-1.11.0.zip
)

FetchContent_MakeAvailable(googletest)

enable_testing()

add_executable(MyTests test.cpp)

target_link_libraries(MyTests PRIVATE MyLib gtest_main)

add_test(NAME MyTest COMMAND MyTests)

테스트 실행

빌드 디렉토리에서 다음 명령어를 실행합니다.

cmake --build . --target MyTests
ctest
  • ctest는 현재 디렉토리의 테스트를 모두 실행합니다.

코드 커버리지 측정

코드 커버리지는 테스트가 코드의 어느 부분을 실행하는지 분석하여 테스트의 효율성을 판단하는 데 도움이 됩니다.

GCC를 사용한 코드 커버리지 설정

컴파일러 플래그 추가

if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    target_compile_options(MyLib PRIVATE --coverage)
    target_link_options(MyLib PRIVATE --coverage)
endif()
  • --coverage 옵션을 추가하여 커버리지 데이터를 수집합니다.

커버리지 리포트 생성

lcov --capture --directory . --output-file coverage.info
genhtml coverage.info --output-directory coverage_report
  • lcov와 genhtml을 사용하여 HTML 형태의 커버리지 리포트를 생성합니다.

CI/CD 파이프라인에 CMake 통합

CI/CD(Continuous Integration/Continuous Deployment)는 코드 변경 시 자동으로 빌드, 테스트, 배포 과정을 실행하여 개발 프로세스를 효율화합니다.

GitHub Actions를 사용한 CI 설정

워크플로우 파일 생성

.github/workflows/ci.yml

name: C/C++ CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build-and-test:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Set up CMake
      uses: lukka/get-cmake@v3

    - name: Build
      run: |
        cmake -B build -S .
        cmake --build build

    - name: Run Tests
      run: |
        cd build
        ctest --output-on-failure
  • actions/checkout@v3: 리포지토리를 체크아웃합니다.
  • lukka/get-cmake@v3: CMake를 설정합니다.
  • 빌드와 테스트를 수행합니다.

GitLab CI/CD를 사용한 CI 설정

.gitlab-ci.yml 파일 생성

stages:
  - build
  - test

build:
  stage: build
  script:
    - cmake -B build -S .
    - cmake --build build
  artifacts:
    paths:
      - build/

test:
  stage: test
  script:
    - cd build
    - ctest --output-on-failure
  • stages: 빌드와 테스트 단계를 정의합니다.
  • artifacts: 빌드 결과물을 다음 단계로 전달합니다.

Docker를 활용한 빌드 환경 통일

Docker를 사용하면 모든 개발자와 CI/CD 시스템에서 동일한 빌드 환경을 사용할 수 있습니다.

Dockerfile 예제

FROM ubuntu:20.04

RUN apt-get update && apt-get install -y \
    build-essential \
    cmake \
    git \
    lcov

WORKDIR /app

COPY . .

RUN cmake -B build -S .
RUN cmake --build build
RUN cd build && ctest
  • 필요한 패키지를 설치하고, 소스를 복사하여 빌드와 테스트를 수행합니다.

Docker를 이용한 로컬 빌드 및 테스트

docker build -t my_project_image .
docker run my_project_image
  • Docker 이미지를 빌드하고 실행하여 테스트를 수행합니다.

CD(Continuous Deployment) 설정

배포 자동화를 위해 CD 파이프라인을 구축할 수 있습니다. 빌드된 결과물을 패키징하여 배포하거나, 컨테이너 이미지를 생성하여 배포 서버에 배포합니다.

예제: Docker 이미지를 Docker Hub에 푸시

GitHub Actions 워크플로우 업데이트

jobs:
  build-test-and-deploy:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Build Docker Image
      run: docker build -t myusername/myproject:latest .

    - name: Log in to Docker Hub
      run: echo "${{ secrets.DOCKER_HUB_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin

    - name: Push Docker Image
      run: docker push myusername/myproject:latest
  • Docker Hub에 로그인하여 이미지를 푸시합니다.
  • secrets를 사용하여 민감한 정보를 보호합니다.

결론

이번 글에서는 CMake를 활용한 테스트 설정과 CI/CD 파이프라인 연동 방법에 대해 알아보았습니다. 이를 통해 자동화된 빌드와 테스트 환경을 구축하여 개발 효율성과 코드 품질을 높일 수 있습니다.

 

다음 글에서는 CMake의 고급 기능인 생성기 표현식커스텀 명령어, 그리고 대규모 프로젝트에서의 모던 CMake 활용 방법에 대해 살펴보겠습니다.

 

반응형