TDD 테스트주도개발/TDD for C++

[googletest문법3]테스트 픽스처 TEST_F() 사용법

CodeMasterSong 2025. 3. 10. 01:01
반응형

Googletest의 TEST_F()의 사용법

Googletest를 이용하여 가장 일반적으로 사용할 수 있는 단위 테스트 방법인 TEST()에 대해서 이전 글을 통해 학습하였다면 이제는 한 걸음 더 나아가 TEST_F()를 살펴 보겠습니다. 


1. TEST() vs. TEST_F() 비교

이전 글에서 소개 했던 TEST()와 TEST_F()의 차이점이 뭘까요?

 

[Googletest문법2]단일테스트 TEST() 작성방법

Google Test를 활용한 단일 테스트 케이스 작성 이번 글에서는 Google Test의 TEST 매크로를 활용하여 단일 테스트 케이스를 작성하는 방법을 알아보겠습니다. 예제는 문자열이 회문인지 판별하는 함

all-tech-hub.tistory.com

TEST()

  • TEST()는 간단한 단일 테스트를 작성할 때 사용합니다.
  • Fixture(공통 환경) 없이 독립적으로 동작하는 테스트 케이스를 정의할 때 유용합니다.
  • 일반적으로 TEST(테스트스위트이름, 테스트이름) 형식을 사용합니다.
#include <gtest/gtest.h> 

TEST(BasicTest, AdditionTest) { 
    int a = 3; int b = 4; 
    EXPECT_EQ(a + b, 7); 
}
 

TEST_F()

  • TEST_F()는 테스트 픽스처(Test Fixture)를 이용하여 여러 테스트가 공통된 리소스, 환경, 초기화/종료 과정을 공유하도록 할 때 사용합니다.
  • Fixture 클래스는 SetUp()과 TearDown() 메서드를 오버라이드하여 테스트 전후로 실행될 로직을 정의합니다.
  • 여러 테스트 케이스가 동일한 객체나 상태를 함께 사용하거나 재사용해야 할 때 유용합니다.
  • TEST_F(테스트픽스처클래스이름, 테스트이름) 형식을 사용합니다.

2. TEST_F()를 이용한 예제

2.1 예제 시나리오

  • 간단한 수학 연산(덧셈, 뺄셈, 곱셈, 나누기)을 수행하는 Calculator 클래스를 테스트한다고 가정합니다.
  • 여러 테스트에서 공통으로 사용할 Calculator 객체를 매번 새로 생성하고, 테스트 종료 후 정리하는 과정을 자동으로 진행하고 싶습니다.

2.2 예제 코드

Calculator 클래스 (Calculator.h / Calculator.cpp)

// Calculator.h
#ifndef CALCULATOR_H
#define CALCULATOR_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; }
    double Divide(double a, double b) { 
        // 0으로 나누는 상황은 예외 처리 필요(실제 구현에서는 throw 등)
        if (b == 0) return 0.0; 
        return a / b; 
    }
};

#endif // CALCULATOR_H
 
// Calculator.cpp 

#include "Calculator.h" 

// 특별히 구현이 필요한 부분이 없으므로 비어있어도 됩니다.

테스트 코드 (test_calculator.cpp)

#include <gtest/gtest.h>
#include "Calculator.h"

// 1. 테스트 픽스처 클래스 정의
class CalculatorTest : public ::testing::Test {
protected:
    // 각 테스트 케이스가 실행되기 전에 호출
    void SetUp() override {
        // Calculator 객체를 생성
        calc = new Calculator();
    }

    // 각 테스트 케이스가 종료된 후 호출
    void TearDown() override {
        // 동적 할당한 객체를 해제
        delete calc;
    }

    // 모든 테스트에서 사용할 공통 객체
    Calculator* calc;
};

// 2. TEST_F() 매크로 사용 예시
TEST_F(CalculatorTest, AdditionTest) {
    // SetUp()에서 생성된 calc를 사용
    EXPECT_EQ(calc->Add(2, 3), 5);
}

TEST_F(CalculatorTest, SubtractionTest) {
    EXPECT_EQ(calc->Subtract(5, 3), 2);
}

TEST_F(CalculatorTest, MultiplicationTest) {
    EXPECT_EQ(calc->Multiply(4, 3), 12);
}

TEST_F(CalculatorTest, DivisionTest) {
    // 정수 6을 2로 나누면 소수점 결과는 3.0
    EXPECT_DOUBLE_EQ(calc->Divide(6, 2), 3.0);
}
 
 
  • 위 코드에서 CalculatorTest 클래스는 ::testing::Test를 상속받아 테스트 픽스처로 동작하며, SetUp()과 TearDown()을 통해 테스트에 필요한 공통 자원을 준비/해제합니다.
  • 그리고 각 테스트 케이스에서는 TEST_F(CalculatorTest, 테스트이름) 구문으로 calc 객체를 이용한 테스트를 수행합니다.
  • 즉 각 테스트에서 필요한 Calculator 객체 생성 부분을 하나로 관리할 수 있도록 CalculatorTest 클래스를 생성하며 이때는 반드시 ::testing::Test를 상속 받아야 합니다. 
  • 각 테스트가 실행될 때마다 SetUp() 메소드가 실행되면서 calc 객체가 생성되고 테스트가 종료될 때 TearDown()이 호출되면서 객체가 소멸되고 있습니다. 

3. 빌드 및 실행 방법 (Windows + VSCode + Cygwin)

3.1 환경 구성

  1. Google Test 설치
    • Cygwin을 통해 googletest를 설치하거나, 소스 코드를 다운받아 직접 빌드할 수 있습니다.
    • 예: Cygwin 설치 시, libgtest-devel 등의 패키지가 제공되는지 확인합니다(없다면 구글테스트 소스를 직접 클론 후 빌드).
  2. VSCode 설정
    • C++ 컴파일러와 include 경로가 잡히도록 c_cpp_properties.json 등을 적절히 설정합니다.
    • googletest 라이브러리가 설치된 디렉터리를 포함하도록 설정합니다.

3.2 예제 디렉터리 구조 예시

my_gtest_example/ 
├── Calculator.h 
├── Calculator.cpp 
├── test_calculator.cpp 
├── CMakeLists.txt (선택사항, CMake 이용 시) 
└── googletest (구글테스트가 별도 폴더로 존재할 수도 있음: 환경에 따라서 다를 수 있음)
 
  • 본 글에서는 Windows에 googletest를 설치하여 기본 경로에서 사용할 수 있도록 설정한 환경이므로 따로 googletest가 존재하지 않습니다.
  • CMakeLists.txt 또한 선택사항 입니다. 먼저 CMakeLists.txt를 사용하지 않아도 이미 설치되어 있는 cygwin 내의 컴파일러를 이용하여 결과를 확인할 수 있습니다. 
  • CMakeLists.txt를 이용하는 방법은 다른 예에서도 자주 사용될 것이므로 본 글에서의 결과는 컴파일러만 이용해 보겠습니다. 
프로젝트구조

3.3 컴파일 (단순 g++ 명령)

다음 2가지 어느 것을 사용해서든 결과를 확인할 수 있습니다.  단 본인이 설치한 버전에 따라서 설정이 달라질 수 있습니다. 

 

(1) GNU 확장 모드로 컴파일하기

  • C++14 표준 모드(-std=c++14) 대신 GNU 확장 모드(-std=gnu++14)로 컴파일하면, Cygwin에서 POSIX 계열 함수를 인식할 수 있도록 해줍니다.
$ g++ -std=gnu++14 test_calculator.cpp Calculator.cpp -lgtest -lgtest_main -pthread -o test_calculator
  • -std=gnu++14는 GCC에서 GNU 확장을 포함한 C++14 모드를 사용하게 만듭니다.
  • 엄격한 C++14(-std=c++14)에서는 POSIX 전용 함수를 기본적으로 노출하지 않을 수 있습니다.
  • Cygwin은 POSIX 계열 환경이긴 하지만, 구글테스트가 사용하는 POSIX 함수가 매크로 등으로 가려져서 오류가 날 수 있습니다.

(2) POSIX 매크로를 명시적으로 정의하여 컴파일하기

$ g++ -std=c++14 -D_POSIX_C_SOURCE=200809L test_calculator.cpp Calculator.cpp \ -lgtest -lgtest_main -pthread -o test_calculator
  • -lgtest -lgtest_main 옵션을 통해 googletest 라이브러리를 링크합니다.
  • -pthread는 googletest에서 필요로 하는 스레드 관련 라이브러리를 연결하기 위해 추가합니다.

3.4 실행

  • 정상적으로 빌드되었다면, 구글 테스트 러너가 모든 테스트를 실행하고 결과를 콘솔에 출력합니다.
$ ./test_calculator
결과
 

4. TEST_F()를 사용할 때의 장점

  1. 공통 코드의 중복 제거: 여러 테스트에서 동일 객체나 같은 로직으로 초기화해야 한다면, SetUp()/TearDown()에 해당 로직을 정의함으로써 코드 중복을 줄일 수 있습니다.
  2. 테스트 간의 독립성 보장: 각 테스트 케이스가 시작할 때마다 새로 초기화된 환경에서 테스트를 진행하므로, 이전 테스트 결과가 다음 테스트에 영향을 미치지 않도록 할 수 있습니다.
  3. 가독성: 테스트 케이스를 모아놓고, Fixture를 통해 어떤 맥락(환경, 객체)을 테스트하는지 명확히 표현할 수 있습니다.

5. 마무리

  • TEST()는 간단 테스트 용도로, TEST_F()는 공유 리소스가 필요한 테스트 환경 구축용으로 이해하면 됩니다.
  • TEST_F()를 사용할 때는 SetUp()과 TearDown() 또는 SetUpTestSuite(), TearDownTestSuite()(클래스 스코프 함수) 등 구글테스트가 제공하는 다양한 훅을 적절히 활용할 수 있습니다.

이상으로 구글 테스트에서 TEST_F()를 사용해 테스트 픽스처를 구성하고 실행하는 방법을 간단한 예제를 통해 살펴보았습니다. 더 많은 예제를 통해 TEST() 뿐만아니라 TEST_F() 사용하는 방법을 익혀야 합니다. 또한 Makefile이나 CMake를 활용하는 컴파일 환경에서도 사용해 보길 바랍니다. 

 

시간이 허락하는 한 또 다른 글에서도 다양한 예제를 통해 익혀볼 수 있는 자료를 만들어 보려고 합니다. 

 

반응형