C++ 유닛 테스트 자동화: Google Test(GTest)로 신뢰성 높이기
✅ C++ 코드 품질을 높이고 싶은 개발자라면 이 글을 주목하세요!
C++ 프로젝트를 진행하다 보면 점점 복잡해지는 코드와 함께 테스트의 중요성도 커지기 마련입니다.
그럴수록 안정성과 유지보수를 위해 자동화된 유닛 테스트 환경을 갖추는 것이 필수가 되죠.
특히 Google Test(GTest)처럼 잘 정리된 프레임워크를 사용하면 테스트가 단순해질 뿐 아니라 협업에서도 큰 도움이 됩니다.
이번 글에서는 C++ 개발자들이 자주 사용하는 유닛 테스트 도구와 함께, 실제 적용 방법 및 활용 팁까지 하나하나 자세히 알려드릴게요.
테스트 자동화에 대한 개념이 어렵게 느껴졌던 분들도 오늘부터는 조금 다르게 느껴질 수 있습니다.
함께 시작해볼까요?
이 글에서는 C++에서 사용할 수 있는 대표적인 테스트 프레임워크인 Google Test를 중심으로 유닛 테스트를 어떻게 구성하고 자동화할 수 있는지를 소개합니다.
테스트 코드를 작성해야 하는 이유부터, 설치 방법, 기초 문법, 실전 예제, 그리고 자주 묻는 질문까지 단계별로 안내해드릴 예정입니다.
유닛 테스트를 처음 접하는 분부터 실제 현업에 적용하고 싶은 분들까지 모두 참고하실 수 있는 실용적인 내용으로 구성되어 있어요.
📋 목차
✅ 유닛 테스트란 무엇인가요?
유닛 테스트(Unit Test)란 소프트웨어 개발에서 하나의 함수나 클래스 같은 최소 단위 단위의 코드가 정확히 동작하는지 검증하는 테스트입니다.
이런 테스트는 보통 자동화된 방식으로 실행되며, 코드 변경 시 버그가 발생했는지를 빠르게 확인할 수 있도록 도와줍니다.
특히 C++처럼 구조가 복잡하고 메모리 관리를 직접 해야 하는 언어에서는, 테스트를 통한 안정성 확보가 매우 중요합니다.
예상치 못한 예외나 논리 오류, 인터페이스 변경 등의 이슈를 사전에 잡아낼 수 있기 때문이죠.
- 🧪기능별 테스트 코드로 예상 결과와 실제 결과 비교
- 🛠️버그 발생 시 정확한 위치와 원인을 빠르게 파악
- 🔄리팩토링 후에도 동작이 유지되는지 검증
물론, 모든 기능을 유닛 테스트로 다 커버할 수는 없습니다.
하지만 핵심 로직이나 자주 변경되는 코드에 대해 유닛 테스트가 잘 작성되어 있다면 전체 시스템의 안정성은 크게 높아집니다.
또한 팀 개발 환경에서는 커밋 전에 테스트를 돌려보는 습관만으로도 수많은 장애를 예방할 수 있죠.
💎 핵심 포인트:
유닛 테스트는 단지 코드의 품질을 높이는 도구가 아니라, 전체 개발 프로세스의 생산성과 협업 효율성을 높여주는 핵심 도구입니다.
🛠️ Google Test(GTest) 설치 방법
Google Test(GTest)는 C++ 진영에서 가장 많이 사용되는 유닛 테스트 프레임워크입니다.
구글에서 직접 오픈소스로 관리하고 있으며, 다양한 플랫폼과 빌드 시스템을 지원해 활용도가 매우 높습니다.
간단한 설정만으로도 바로 테스트 코드를 작성하고 실행할 수 있어, 초보자도 쉽게 접근할 수 있다는 장점이 있습니다.
GTest 설치 방법은 사용하는 빌드 도구에 따라 조금씩 다르지만, 대표적으로 많이 사용하는 CMake 기반의 설치 과정을 예시로 들어 설명드릴게요.
# GoogleTest를 FetchContent로 설치하는 CMake 예제
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/refs/heads/main.zip
)
FetchContent_MakeAvailable(googletest)
enable_testing()
add_executable(MyTest main_test.cpp)
target_link_libraries(MyTest gtest_main)
include(GoogleTest)
gtest_discover_tests(MyTest)
위 방식은 GoogleTest를 외부 라이브러리로 자동 다운로드하여 프로젝트 내부에 포함시키는 형태입니다.
추가적인 빌드 옵션 없이도 테스트 실행 파일이 생성되며, CTest와 통합하여 CI/CD 환경에서도 손쉽게 활용할 수 있습니다.
💡 TIP: 이미 빌드된 GTest 라이브러리를 사용하는 경우에는 CMake 대신 직접 링크 옵션을 추가하거나 Makefile을 통해 빌드할 수도 있습니다.
GTest 설치가 완료되면 이제부터는 다양한 테스트 케이스를 자유롭게 작성하고, 실행 결과를 통해 코드의 안정성을 높일 수 있게 됩니다.
이제 다음 단계에서는 GTest의 기본 구조와 주요 문법을 함께 살펴보겠습니다.
🔍 GTest 기본 구조와 주요 문법
Google Test는 간결하면서도 확장성 있는 문법 구조를 가지고 있습니다.
기본적인 테스트 함수 하나만으로도 다양한 조건 검증이 가능하며, 필요한 경우 Fixture 기반의 테스트 구성도 지원합니다.
처음 GTest를 접하시는 분들을 위해, 핵심적인 문법 구조를 아래 예제와 함께 정리해볼게요.
// 기본 테스트 예제
#include <gtest/gtest.h>
TEST(MathTest, Addition) {
EXPECT_EQ(2 + 2, 4);
EXPECT_NE(2 + 2, 5);
}
위 예제처럼 TEST() 매크로를 사용해 테스트 케이스를 작성할 수 있습니다.
매크로는 TEST(테스트 그룹명, 테스트 이름) 형식이며, 내부에는 여러 개의 검증 구문을 포함할 수 있습니다.
- ✅
EXPECT_EQ(a, b)– 두 값이 같아야 통과 - ❌
EXPECT_NE(a, b)– 두 값이 달라야 통과 - ⚠️
ASSERT_TRUE(condition)– 조건이 true여야 테스트 통과
또한 ASSERT_* 계열은 실패 시 테스트를 즉시 중단하며, EXPECT_*는 실패해도 다음 라인까지 실행되는 차이점이 있습니다.
테스트 목적에 따라 두 가지를 적절히 조합해 사용하는 것이 중요합니다.
💎 핵심 포인트:
GTest는 단순히 검증 도구를 넘어서 테스트 환경 구성, 테스트 반복 실행, 조건 분기 테스트까지 폭넓은 기능을 제공합니다.
기본 구조를 이해했다면, 이제 다음으로는 실전 예제를 통해 실제 테스트 코드가 어떻게 작성되는지를 더 자세히 살펴보겠습니다.
📌 실전 예제로 배우는 테스트 작성법
기본 문법을 익혔다면 이제는 실제 프로젝트 코드에 테스트를 어떻게 적용하는지를 알아볼 차례입니다.
단순한 수학 계산이 아닌, 클래스와 객체를 다루는 예제를 중심으로 테스트 구성 방식을 이해해보겠습니다.
예를 들어, 간단한 Calculator 클래스가 있다고 가정해 보겠습니다.
이 클래스는 덧셈과 나눗셈을 처리하며, 나눗셈에서 0으로 나눌 경우 예외를 발생시킵니다.
class Calculator {
public:
int Add(int a, int b) { return a + b; }
int Divide(int a, int b) {
if (b == 0) throw std::invalid_argument("Divide by zero");
return a / b;
}
};
이제 위 클래스를 테스트하는 GTest 코드는 다음과 같이 작성할 수 있습니다.
TEST(CalculatorTest, AddTest) {
Calculator calc;
EXPECT_EQ(calc.Add(3, 2), 5);
}
TEST(CalculatorTest, DivideTest) {
Calculator calc;
EXPECT_EQ(calc.Divide(10, 2), 5);
}
TEST(CalculatorTest, DivideByZeroTest) {
Calculator calc;
EXPECT_THROW(calc.Divide(10, 0), std::invalid_argument);
}
이처럼 실전 테스트에서는 단순한 값 비교 외에도 예외 처리, 경계 조건, 오류 상황까지 폭넓게 검증해야 합니다.
또한 여러 테스트 케이스가 실패 없이 통과할 수 있도록 코드 자체도 테스트 가능하게 구성하는 것이 중요하죠.
⚠️ 주의: 테스트 코드를 작성할 때 너무 많은 로직을 포함하거나, 실제 시스템 환경에 의존하지 않도록 주의해야 합니다. 테스트는 독립적이고 반복 실행 가능해야 합니다.
실전 테스트를 통해 실제 업무에서 발생할 수 있는 다양한 시나리오를 사전에 점검하고, 오류를 줄이는 개발 문화를 만들어갈 수 있습니다.
다음 단계에서는 이렇게 작성된 테스트를 CI/CD에 통합하는 방법을 알려드릴게요.
🚀 CI/CD 파이프라인에 테스트 통합하기
유닛 테스트는 단순히 로컬에서 실행하고 끝나는 것이 아니라, CI/CD 파이프라인에 자동으로 포함되어야 진정한 효과를 발휘합니다.
이렇게 하면 코드가 커밋될 때마다 테스트가 자동으로 실행되어, 오류를 조기에 발견하고 배포 품질을 유지할 수 있습니다.
CI 툴로는 GitHub Actions, GitLab CI, Jenkins, Travis CI 등이 있으며, 대부분 GTest를 손쉽게 통합할 수 있습니다.
그중에서도 GitHub Actions를 예로 들어 간단한 워크플로 구성을 보여드릴게요.
# .github/workflows/test.yml
name: Run GTest on push
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Dependencies
run: sudo apt-get install cmake g++ -y
- name: Configure
run: cmake -Bbuild -H.
- name: Build
run: cmake --build build
- name: Run Tests
run: ctest --test-dir build
이 스크립트는 main 브랜치에 코드가 푸시될 때마다 자동으로 빌드하고, CMake를 이용해 테스트를 실행합니다.
이처럼 CI 환경에 테스트를 연결하면 실수로 인한 오류나 배포 실패를 방지할 수 있습니다.
- 🔄테스트가 실패하면 배포 중단
- 📦빌드-테스트-배포 흐름을 자동화
- 👥협업 중 코드 오류 발생 시 즉시 알림
CI/CD에 테스트를 연동하면 코드 품질이 눈에 띄게 향상되며, 운영 환경으로의 배포 안정성도 보장받을 수 있습니다.
이제 개발팀 전체가 테스트 자동화를 통해 더 안전하고 빠르게 소프트웨어를 릴리즈할 수 있는 환경을 갖추게 되는 셈이죠.
❓ 자주 묻는 질문 (FAQ)
Google Test는 꼭 필요한가요?
GTest는 어떤 플랫폼에서 사용할 수 있나요?
기존 프로젝트에 테스트를 추가하려면 어떻게 하나요?
GTest에서 테스트 이름은 어떻게 정하나요?
TEST(UserTest, LoginSuccess)와 같이 기능 단위로 명확하게 지정하는 것이 좋습니다.
GTest 실행 결과를 보고서로 만들 수 있나요?
EXPECT와 ASSERT의 차이는 뭔가요?
테스트 속도가 느릴 경우 어떻게 하나요?
Mock 테스트는 어떻게 활용하나요?
🔎 C++ 유닛 테스트 자동화로 얻는 진짜 이점
이번 글에서는 C++에서 유닛 테스트를 어떻게 구성하고, Google Test(GTest)를 활용해 자동화하는 방법을 단계별로 살펴봤습니다.
단순히 테스트 코드를 작성하는 수준을 넘어, 실전 환경에서의 예제 적용, CI/CD 파이프라인 통합까지 함께 다루면서 유닛 테스트의 진정한 가치에 대해 이해할 수 있었죠.
유닛 테스트는 코드를 견고하게 만들고, 변경에 강한 구조로 이끄는 핵심 개발 습관입니다.
특히 협업 환경이나 장기적인 유지보수가 필요한 프로젝트라면 테스트 자동화는 더 이상 선택이 아닌 필수입니다.
Google Test와 같은 도구는 그 과정을 훨씬 쉽게 만들어주며, 개발자의 실수를 줄이고 품질을 높이는 데 큰 역할을 합니다.
앞으로 여러분의 프로젝트에도 유닛 테스트 자동화를 적극 도입해보세요.
코드가 점점 더 자신감 있게 작성되고, 개발이 한층 더 효율적이고 안정적으로 변화할 수 있을 거예요.
🏷️ 관련 태그:C++, 유닛테스트, GoogleTest, GTest설치법, 테스트자동화, CMake, 테스트코드작성, 개발팁, 코드품질, CI/CD연동