C++ Unit Testing | "단위 테스트" 가이드
이 글의 핵심
C++ Unit Testing에 대한 실전 가이드입니다. 개념부터 실무 활용까지 예제와 함께 상세히 설명합니다.
단위 테스트란?
개별 함수나 클래스를 독립적으로 테스트
// 테스트할 코드
int add(int a, int b) {
return a + b;
}
// 테스트 코드
TEST(AddTest, BasicTest) {
EXPECT_EQ(add(2, 3), 5);
EXPECT_EQ(add(-1, 1), 0);
}
Google Test 기본
#include <gtest/gtest.h>
// 테스트 작성
TEST(TestSuiteName, TestName) {
EXPECT_EQ(1 + 1, 2);
ASSERT_TRUE(true);
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
# 컴파일
g++ test.cpp -lgtest -lgtest_main -pthread
# 실행
./a.out
실전 예시
예시 1: 기본 테스트
#include <gtest/gtest.h>
class Calculator {
public:
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) {
if (b == 0) throw std::invalid_argument("0으로 나눌 수 없음");
return a / b;
}
};
TEST(CalculatorTest, AddTest) {
Calculator calc;
EXPECT_EQ(calc.add(2, 3), 5);
EXPECT_EQ(calc.add(-1, 1), 0);
}
TEST(CalculatorTest, DivideTest) {
Calculator calc;
EXPECT_EQ(calc.divide(10, 2), 5);
EXPECT_THROW(calc.divide(10, 0), std::invalid_argument);
}
예시 2: Fixture 사용
class VectorTest : public ::testing::Test {
protected:
void SetUp() override {
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
}
void TearDown() override {
vec.clear();
}
std::vector<int> vec;
};
TEST_F(VectorTest, SizeTest) {
EXPECT_EQ(vec.size(), 3);
}
TEST_F(VectorTest, ElementTest) {
EXPECT_EQ(vec[0], 1);
EXPECT_EQ(vec[1], 2);
}
예시 3: 매개변수화 테스트
class AddTest : public ::testing::TestWithParam<std::tuple<int, int, int>> {};
TEST_P(AddTest, ParameterizedTest) {
auto [a, b, expected] = GetParam();
EXPECT_EQ(add(a, b), expected);
}
INSTANTIATE_TEST_SUITE_P(
AddTests,
AddTest,
::testing::Values(
std::make_tuple(1, 2, 3),
std::make_tuple(0, 0, 0),
std::make_tuple(-1, 1, 0)
)
);
예시 4: Mock 객체
#include <gmock/gmock.h>
class Database {
public:
virtual ~Database() = default;
virtual bool connect() = 0;
virtual std::string query(const std::string& sql) = 0;
};
class MockDatabase : public Database {
public:
MOCK_METHOD(bool, connect, (), (override));
MOCK_METHOD(std::string, query, (const std::string&), (override));
};
TEST(ServiceTest, MockTest) {
MockDatabase mockDb;
EXPECT_CALL(mockDb, connect())
.WillOnce(::testing::Return(true));
EXPECT_CALL(mockDb, query("SELECT *"))
.WillOnce(::testing::Return("result"));
EXPECT_TRUE(mockDb.connect());
EXPECT_EQ(mockDb.query("SELECT *"), "result");
}
Catch2 사용
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
TEST_CASE("Calculator tests", "[calculator]") {
Calculator calc;
SECTION("Addition") {
REQUIRE(calc.add(2, 3) == 5);
}
SECTION("Division") {
REQUIRE(calc.divide(10, 2) == 5);
REQUIRE_THROWS(calc.divide(10, 0));
}
}
자주 발생하는 문제
문제 1: 테스트 의존성
// ❌ 테스트 간 의존성
TEST(BadTest, Test1) {
globalVar = 10;
}
TEST(BadTest, Test2) {
EXPECT_EQ(globalVar, 10); // Test1에 의존
}
// ✅ 독립적 테스트
TEST(GoodTest, Test1) {
int var = 10;
EXPECT_EQ(var, 10);
}
TEST(GoodTest, Test2) {
int var = 10;
EXPECT_EQ(var, 10);
}
문제 2: 너무 큰 테스트
// ❌ 여러 것을 한 번에 테스트
TEST(BadTest, EverythingTest) {
// 10개 함수 테스트
}
// ✅ 하나씩 테스트
TEST(GoodTest, AddTest) {
// add 함수만
}
TEST(GoodTest, SubtractTest) {
// subtract 함수만
}
문제 3: 외부 의존성
// ❌ 파일 시스템 의존
TEST(BadTest, FileTest) {
std::ifstream file("/tmp/test.txt");
// 파일 없으면 실패
}
// ✅ Mock 사용
TEST(GoodTest, FileTest) {
MockFileSystem fs;
// Mock으로 제어
}
문제 4: 느린 테스트
// ❌ 느린 작업
TEST(BadTest, SlowTest) {
std::this_thread::sleep_for(std::chrono::seconds(10));
}
// ✅ 빠른 테스트
TEST(GoodTest, FastTest) {
// 즉시 완료
}
TDD (Test-Driven Development)
// 1. 실패하는 테스트 작성
TEST(StackTest, PushTest) {
Stack<int> stack;
stack.push(10);
EXPECT_EQ(stack.top(), 10);
}
// 2. 최소 구현
template<typename T>
class Stack {
std::vector<T> data;
public:
void push(const T& value) {
data.push_back(value);
}
T top() const {
return data.back();
}
};
// 3. 리팩토링
FAQ
Q1: 단위 테스트는 언제?
A:
- 새 기능 추가
- 버그 수정
- 리팩토링
Q2: Google Test vs Catch2?
A:
- Google Test: 기능 많음
- Catch2: 간단, 헤더 온리
Q3: 테스트 커버리지 목표는?
A:
- 최소 70%
- 핵심 로직 100%
Q4: Mock은 언제?
A:
- 외부 의존성
- 네트워크, 파일
- 느린 작업
Q5: TDD 장점은?
A:
- 설계 개선
- 버그 조기 발견
- 문서화
Q6: 단위 테스트 학습 리소스는?
A:
- Google Test 문서
- “Test Driven Development”
- Catch2 문서
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- C++ Google Test | gtest 설치부터 TEST·EXPECT_EQ
- C++ Benchmarking | “벤치마킹” 가이드
- C++ 코드 커버리지 완벽 가이드 | gcov, lcov, Codecov 실전 활용
관련 글
- C++ 시리즈 전체 보기
- C++ Adapter Pattern 완벽 가이드 | 인터페이스 변환과 호환성
- C++ ADL |
- C++ Aggregate Initialization |