자바스크립트를 활성화 해주세요

GoogleTest User's Guide: 입문하기

 ·  ☕ 17 min read

본 글은 GoogleTest공식 문서를 번역한 것입니다. 원문은 여기서 확인하실 수 있습니다.
현재 글은 2021년 8월 4일 형상을 기준으로 번역하였으므로 시간이 지남에 따라 원문과 차이가 있을 수 있습니다.
This post is translated version of GoogleTest User’s Guide webpage. You can check original post by link.
Current translation is based on the version of August 4, 2021. So the contents may differ when time goes by.

서론: 왜 GoogleTest인가?

GoogleTest 를 통해 더 나은 C++ 테스트를 작성할 수 있습니다.

GoogleTest는 Testing Technology 팀에서 개발한 테스트 프레임워크로서, 구글의 특정한 요구사항과 제약 조건을 염두하여 개발된 프레임워크입니다. 여러분이 C++로 코드 작성을 하고 있다면, (환경이 Linux던, Windows나 Mac이던 관계 없이) GoogleTest가 도움을 줄 수 있습니다. 또한 GoogleTest는 단위 테스트 뿐만 아니라 모든 종류의 테스트를 지원합니다.

그렇다면 무엇이 좋은 테스트고, GoogleTest는 어떻게 이걸 가능케 할까요? 우리는 이렇게 생각했습니다.

  1. 테스트는 독립적 이고 반복적 일수 있어야 합니다.
    다른 테스트의 결과에 영향을 받아서 성공 혹은 실패하는 테스트를 디버깅하기란 어렵습니다.
    GoogleTest는 각 테스트를 다른 객체에 격리하여 실행합니다.
    만약 어떤 테스트가 실패하더라도, GoogleTest는 해당 테스트만 독립적으로 실행하여 디버깅을 빨리 할 수 있게 해줍니다.
  2. 테스트는 테스트 대상이 될 코드의 구조를 반영하고, 잘 구성되어야 합니다.
    GoogleTest는 관련된 테스트들을 test suite로 묶어서 데이터와 서브루틴을 공유할 수 있습니다.
    이러한 일반적인 패턴은 테스트를 쉽게 이해하고, 테스트의 관리를 쉽게 합니다.
    일관성은 특히 사람들이 프로젝트를 변경하여 새로운 코드 기반에서 일할 때 도움을 줍니다.
  3. 테스트는 이식성 이 있어야 하며, 재사용 가능해야합니다.
    구글은 플랫폼 중립적인 코드를 많이 가지고 있습니다. 그리고 이 코드들의 테스트 또한 플랫폼 중립적이어야 합니다.
    GoogleTest는 다른 운영체제, 다른 컴파일러, 예외 처리의 지원 여부와 관계 없이 동작합니다.
    즉, GoogleTest를 통해 다양한 환경(구성)에서 테스트를 할 수 있습니다.
  4. 만약 테스트가 실패한다면, 해당 문제에 대해 가능한 많은 정보 를 제공해야 합니다.
    GoogleTest는 첫 테스크가 실패했다고 멈추지 않습니다. 대신 현재 테스트만 멈추고, 다음 테스트를 계속 진행합니다.
    또한 각 테스트에서 심각하지 않은 실패의 경우, 해당 실패 여부만 기록하고 테스트를 계속 진행할 수도 있습니다.
    결론적으로 여러분은 한번의 실행-수정-컴파일 순환만으로도 여러 버그를 찾고 수정할 수 있습니다.
  5. 테스팅 프레임워크는 테스트 작성자들이 잡무로부터 해방되고, 테스트의 내용 에 집중할 수 있게 해야 합니다.
    구글 테스트는 모든 정의된 테스트 목록을 추적하며, 사용자가 각 테스트들을 실행하기 위해 직접 나열하지 않아도 되게 도와줍니다.
  6. 테스트는 빠르게 진행되어야 합니다.
    여러분은 구글 테스트를 통해 set-up/tear-down(테스트를 위한 자원 설정 및 해제) 한번으로 테스트 간의 자원을 재사용 및 공유할 수 있습니다.
    (물론 테스트 간의 의존성을 만들지 않습니다.)

GoogleTest는 인기있는 xUnit 구조를 기반으로 만들어졌기 때문에, 여러분이 JUnit이나 PyUnit을 이전에 사용해봤다면 익숙하실 것입니다. 만약 익숙하지 않더라도 10분정도면 기초를 배우고 새로 시작하는데 충분할 것입니다. 시작해봅시다!

명명법에 대한 주의사항

테스트(Test), 테스트 케이스(Test Case), 테스트 모음(Test Suite) 의 정의가 달라 혼란스러울 수 있으니 주의 바랍니다.

이전부터 GoogleTest는 관련된 테스트들을 묶은 것을 테스트 케이스 라고 정의했습니다. 반면 ISTQB(International Software Testing Qualifications Board)의 자료 등의 문서나, 소프트웨어 품질 관련 다양한 책에서는 이 개념을 테스트 모음 으로 정의합니다.

위와 관련된 단어로, GoogleTest에서 테스트 라 부르는 용어는 ISTQB 등에서는 테스트 케이스 로 정의합니다.

테스트 란 용어는 일반적으로 ISTQB에서 정의한 테스트 케이스 를 포함하여 충분히 넓은 의미를 가진 단어이므로 크게 문제되지 않습니다. 하지만 GoogleTest에서 사용되었던 테스트 케이스 는 모순된 의미로 혼동을 줄 수 있습니다.

최근 GoogleTest에서도 테스트 케이스 란 용어를 테스트 모음 으로 변경하고 있습니다. 이전의 TestCase API는 천천히 사장되거나 TestSuite API로 리팩토링되고 있습니다.

그러므로 아래 용어의 정의에 대해 주의하시기 바랍니다.

의미GoogleTest 용어ISTQB 용어
특정 프로그램을 지정된 입력값으로 실행하여 결과를 검증TEST()Test Case

기본 개념

GoogleTest를 사용한다면, 주어진 조건이 참인지 확인하기 위해 단언문(assertion) 을 작성하는 것으로 시작하게 될 것입니다. 단언문의 결과는 성공(success), 심각하지 않은 실패(nonfatal failure) 혹은 심각한 실패(fatal failure) 중 하나입니다. 만약 심각한 실패가 발생한다면 현재 함수를 중지시킵니다. 이를 제외한 나머지는 프로그램을 정상적으로 계속 실행합니다.

테스트 는 단언문을 통해 테스트 할 코드의 행동을 검증합니다. 만약 테스트 중 충돌이 발생하거나 실패한 단언문이 있다면 해당 테스트는 실패 한 것입니다. 만약 그런 문제가 없었다면 해당 테스트는 성공 한 것입니다.

테스트 모음 은 한개 혹은 그 이상의 테스트를 갖고 있습니다. 테스트 할 코드의 구조를 반영하여 테스트들을 적절한 테스트 모음으로 묶는 것이 좋습니다. 만약 테스트 모음에 속한 여러 테스트들이 공통적인 객체나 서브루틴(함수)를 사용해야 한다면, 공통된 부분을 테스트 고정부(Test Fixture) 클래스에 넣을 수 있습니다.

테스트 프로그램 은 여러 테스트 모음을 가질 수 있습니다.

이제 테스트 프로그램을 작성하는 방법을 알려드릴 것입니다. 개별적인 단언문 수준부터 시작하여, 테스트와 테스트 모음을 만드는 법 까지 다룰 것입니다.

단언문

GoogleTest의 단언문은 함수 호출을 닮은 매크로입니다. 클래스나 함수의 동작에 대한 단언문을 작성하여 테스트를 할 수 있습니다. 만약 단언문을 통과하지 못하면 GoogleTest에서 해당 단언문의 소스 파일 이름, 몇 번째 줄에 있는 단언문인지, 실패에 대한 추가 정보를 가진 메시지를 출력합니다. GoogleTest의 실패 정보 출력에 덧붙여 나올 사용자 정의 메시지를 직접 작성할 수도 있습니다.

단언문은 같은 테스트를 하지만 결과가 달라지는 두가지 형태가 제공됩니다. ASSERT_*() 방식은 실패시 심각한 실패를 발생시키고, 현재 함수를 중지합니다. EXPECT_*() 방식은 심각하지 않은 실패를 발생시키며, 현재 함수를 중지시키지 않습니다. 테스트에서 한개 이상의 실패를 보고받을수 있기 때문에 대부분 EXPECT_*()를 선호하는 편입니다. 하지만 단언문의 실패 이후에 동작이 유지되는 것이 부적절하다면, ASSERT_*()를 사용해야 합니다.

ASSERT_*()에서 실패하면 현재 함수에서 즉시 반환하므로 해당 단언문 이후에 처리되는 정리 코드들이 생략될 수 있으며, 공간 낭비(메모리 누수)를 일으킬 수도 있습니다. 해당 공간 낭비의 특성에 따라 수정이 필요할 수도 있지만, 수정할 만한 가치가 없을 수도 있습니다. 혹시나 힙 영역의 누수를 확인하는 도구를 사용할 때, 이런 실패 과정에서 누수가 발생하는 것이 감지될 수도 있으므로 해당 부분을 항상 생각하는 것이 좋습니다.

단언문에 실패에 대한 사용자 정의 메시지를 추가하려면, 단언문 매크로에 << 연산자를 통해 스트림을 전달하면 됩니다. (해당 연산자를 여러번 사용하여 여러 번의 스트림 전달도 가능합니다.) 아래 예시를 보면 ASSERT_EQ()EXPECT_EQ() 매크로를 사용하여 값의 일치 여부를 검증하고 있습니다.

ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";

for (int i = 0; i < x.size(); ++i) {
  EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
}

C 문자열과 string 객체를 포함하여 ostream으로 스트림할 수 있는 것들은 모두 단언문 매크로에 스트림 할 수 있습니다. 확장 문자열(wide string, Windows에서 UNICODE 환경이라면 wchar_t*, TCHAR*, std::wstring)를 매크로에 스트림한다면, 출력될 때 UTF-8로 변환되어 출력됩니다.

GoogleTest는 여러 방법으로 여러분의 코드를 검증하게 해 줄 단언문들을 제공합니다. 부울 논리 조건(Boolean conditions), 비교 연산자를 통한 값 비교, 문자열 검증, 부동소수점 값 비교 등을 할 수 있습니다. 심지어 사용자 지정 서술부(predicate)를 사용하여 더 복잡한 상태를 검증하는 것도 가능하게 합니다. GoogleTest가 제공하는 모든 단언문의 목록을 보려면 단언문 참고를 참고하길 바랍니다.

간단한 테스트

테스트를 작성하는 법은 아래와 같습니다.

  1. TEST() 매크로를 통해 테스트 함수를 정의하고 이름을 붙입니다. 테스트 함수는 값을 반환하지 않는 일반적인 C++ 함수입니다.
  2. 테스트 함수 내에서, 유효한 C++ 구문을 모두 사용할 수 있으며, 다양한 GoogleTest 단언문을 통해 값을 확인할 수 있습니다.
  3. 테스트의 결과는 단언문에 의해 결정됩니다. 만약 함수 내 단언문 중 하나라도 실패하거나(심각성 여부와 관계 없이), 테스트 실행 중 충돌이 발생한다면 해당 태스트는 실패합니다. 실패가 발생하지 않았다면 해당 테스트는 성공입니다.
TEST(TestSuiteName, TestName) {
  ... test body ...
}

TEST()의 인자는 일반화에서 구체화 방식으로 입력합니다. 첫 번째 인자에는 테스트 모음의 이름을, 두 번째 인자에는 테스트 모음 내 해당 테스트의 이름을 작성합니다. 두 이름 모두(TEST()의 인자) 언더바(_)를 포함하지 않으면서 유효한 C++ 식별자여야 합니다. 한 테스트의 정식 명칭은 테스트 모음의 이름과 개별적인 이름의 조합으로 이루어집니다. 개별적인 이름은 테스트 모음이 다르다면 똑같은 이름이 존재할 수도 있습니다.

예를 들어, 아래와 같이 간단한 정수 함수가 있다고 했을 때,

int Factorial(int n);  // Returns the factorial of n

해당 함수를 위한 테스트 모음은 이렇게 작성될 수 있습니다.

// Tests factorial of 0.
TEST(FactorialTest, HandlesZeroInput) {
  EXPECT_EQ(Factorial(0), 1);
}

// Tests factorial of positive numbers.
TEST(FactorialTest, HandlesPositiveInput) {
  EXPECT_EQ(Factorial(1), 1);
  EXPECT_EQ(Factorial(2), 2);
  EXPECT_EQ(Factorial(3), 6);
  EXPECT_EQ(Factorial(8), 40320);
}

GoogleTest는 테스트 모음 단위로 테스트 결과를 묶습니다. 그러므로 논리적으로 서로 관계 있는 테스트들은 하나의 테스트 모음에 같이 담겨 있어야 합니다. 즉, TEST()의 첫 번째 인자는 같아야 합니다. 위의 예시를 보면, HandleZeroInputHandlePositiveInput 두 개의 테스트는 FactorialTest 테스트 모음에 속해있는 것을 볼 수 있습니다.

테스트 모음과 테스트 이름을 지을때, 함수와 클래스의 작명법 규정을 따르는 것이 좋습니다.

사용 가능 환경: Linux, Windows, Mac.

테스트 고정부: 여러 테스트에 같은 설정 사용하기

만약 테스트를 작성하던 중 둘 이상의 테스트가 비슷한 값으로 테스트를 한다면, 테스트 고정부 를 활용할 수 있습니다. 테스트 고정부를 통해 동일한 객체의 설정을 서로 다른 테스트에서 재사용할 수 있습니다.

고정부를 만드는 방법은 아래와 같습니다.

  1. ::testing::Test 클래스로부터 상속을 받습니다. 클래스 내부는 protected:로 시작하여, 자식 클래스가 고정부 클래스의 멤버를 접근할수 있게 합니다.
  2. 클래스 내부에 본인이 사용하고자 하는 객체를 선언합니다.
  3. 필요하다면, 기본 생성자 혹은 SetUp() 함수를 작성하여 각 테스트를 위한 객체의 상태를 준비할 수 있습니다.
    자주 하는 실수 중, SetUp() 함수 정의에서 대소문자 구분을 확실히 하지 못하는 경우가 있습니다.
    만약 C++11이라면 override 키워드를 사용하면 오타 여부를 확실히 알 수 있습니다.
  4. 필요하다면, 소멸자나 TearDown() 함수를 작성하여 이전 SetUp() 함수에서 할당했던 자원들을 해제할 수 있습니다.
    어떤 경우에 생성자/소멸자를 사용해야 하는지, 혹은 SetUp()/TearDown() 함수를 사용해야 하는지 궁금하다면, FAQ를 읽어보길 바랍니다.
  5. 필요하다면, 테스트 내에서 공유될 서브루틴을 정의할 수 있습니다.

테스트 고정부를 사용한다면, 기존 테스트 작성에 사용하던 매크로인 TEST() 대신 TEST_F()를 사용해야 고정부 내부에 정의된 객체와 서브루틴을 사용할 수 있습니다.

TEST_F(TestFixtureName, TestName) {
  ... test body ...
}

TEST() 매크로를 사용할 때 처럼, 첫 번째 인자는 테스트 모음의 이름을 나타냅니다. 다만 TEST_F()에 넣는 테스트 모음 이름은 테스트 고정부 클래스의 이름과 같아야 합니다. 예상했겠지만, 매크로에 추가된 _F라는 표현은 고정부를 뜻합니다.

안타깝게도 C++의 매크로에서는 단일 매크로를 이용해 두 종류의 테스트를 알아서 생성할 수 없습니다. (기존 TEST()를 사용하는 테스트와, TEST_F()를 사용하는 테스트) 매크로를 잘못 사용한다면 컴파일 에러가 발생할 수 있습니다.

코드 작성에 있어 테스트 고정부 클래스의 정의가 끝난 뒤 TEST_F() 매크로에서 테스트 고정부 클래스를 사용해야 합니다. 만약 이 순서를 지키지 않는다면 “virtual outside class declaration“와 같은 컴파일 오류를 보게 될 것입니다.

TEST_F()를 통해 테스트가 정의되었다면, GoogleTest에서 새로운 테스트 고정부를 런타임에 생성하고, SetUp()을 통해 즉시 초기화하고, 테스트를 수행한 뒤, TearDown()을 통해 정리하고 해당 테스트 고정부 객체를 삭제할 것입니다. 한 테스트 모음에 있는 다른 테스트들은 개별적인 테스트 고정부 객체를 갖게 됩니다. GoogleTest는 언제나 기존 테스트 고정부 객체를 삭제하고 나서야 새로운 테스트 고정부 객체를 생성합니다. 또한 테스트 고정부 객체는 여러 테스트에서 재활용되지 않습니다. 특정 테스트에서 테스트 고정부에 일으킨 변화는 다른 테스트에 영향을 주지 않도록 되어있습니다.

이제 예시로 Queue라는 선입선출 큐 클래스에 대한 테스트를 작성하는 경우를 보겠습니다. 해당 클래스의 인터페이스는 아래와 같습니다.

template <typename E>  // E is the element type.
class Queue {
 public:
  Queue();
  void Enqueue(const E& element);
  E* Dequeue();  // Returns NULL if the queue is empty.
  size_t size() const;
  ...
};

먼저 고정부 클래스를 정의하겠습니다. 일반적으로 Foo라는 클래스를 테스트한다면, 고정부 클래스의 이름은 FooTest로 짓습니다.

class QueueTest : public ::testing::Test {
 protected:
  void SetUp() override {
     q1_.Enqueue(1);
     q2_.Enqueue(2);
     q2_.Enqueue(3);
  }

  // void TearDown() override {}

  Queue<int> q0_;
  Queue<int> q1_;
  Queue<int> q2_;
};

위의 예시에서 각 테스트가 끝날 때 마다 굳이 정리해야 할 필요가 없기 때문에(소멸자를 통해 알아서 처리되기 때문에) TearDown()은 정의하지 않았습니다. 이제 TEST_F()를 통해 이 고정부를 사용하는 테스트를 작성하겠습니다.

TEST_F(QueueTest, IsEmptyInitially) {
  EXPECT_EQ(q0_.size(), 0);
}

TEST_F(QueueTest, DequeueWorks) {
  int* n = q0_.Dequeue();
  EXPECT_EQ(n, nullptr);

  n = q1_.Dequeue();
  ASSERT_NE(n, nullptr);
  EXPECT_EQ(*n, 1);
  EXPECT_EQ(q1_.size(), 0);
  delete n;

  n = q2_.Dequeue();
  ASSERT_NE(n, nullptr);
  EXPECT_EQ(*n, 2);
  EXPECT_EQ(q2_.size(), 1);
  delete n;
}

위의 예시의 경우 ASSERT_*()EXPECT_*() 단언문을 함께 사용하는 것을 볼 수 있습니다. 경험적으로 EXPECT_*()는 단언문 실패 이후에도 테스트를 계속 진행하며 추가적인 오류를 더 드러내고자 할 때 사용합니다. ASSERT_*()는 해당 단언문이 실패한 뒤의 코드를 진행하는것은 무의미하다고 생각할 때 사용합니다. 예를 들어 Dequeue 관련 테스트에서 두 번째 단언문에 사용된 ASSERT_NE(n, nullptr)를 보자. 해당 단언문 이후의 코드에서는 포인터 변수 n에 대한 간접 접근(dereference)이 수행되어야 하는데, nNULL이면 segfault가 발생할 수 있으므로 이와 같이 사용한 것을 볼 수 있습니다.

위와 같은 고정부 기반의 테스트를 수행하면 아래와 같은 순서로 동작합니다.

  1. GoogleTest가 QueueTest 객체를 생성합니다. (이 객체를 t1이라 부르겠습니다.)
  2. t1.SetUp()으로 t1 객체가 초기화됩니다.
  3. 첫 테스트(IsEmptyInitially)가 t1에서 수행됩니다.
  4. 해당 테스트가 끝나고 난 뒤, t1.TearDown()을 통해 내부가 정리됩니다.
  5. t1 객체가 소멸되었습니다.
  6. 위와 같은 과정이 또 다른 QueueTest 객체에서 수행된다. 이번에는 DequeueWorks 테스트를 수행합니다.

사용 가능 환경: Linux, Windows, Mac.

테스트 실행 방법

TEST()TEST_F() 매크로를 사용하면 GoogleTest의 테스트 목록에 암묵적으로 등록이 됩니다. 다른 C++ 테스팅 프레임워크에서는 각 테스트를 정의하고, 그 테스트들을 실행시키기 위해 다시 그 목록을 나열했어야 했겠지만, GoogleTest에서는 그럴 필요가 없습니다.

테스트들을 정의하고 나서, RUN_ALL_TESTS()를 통해 직접 테스트를 수행할 수 있습니다. 모든 테스트가 성공했다면 해당 매크로는 0을 반환할 것이고, 하나라도 실패했다면 1을 반환할 것입니다. 참고로 RUN_ALL_TESTS()는 링크된 수준에서 접근할 수 있는 모든 테스트 를 수행합니다. 즉, 현재 테스트 모음과 다를 수 있으며, 심지어 다른 소스파일에 있는 테스트들도 수행될 수 있습니다.

RUN_ALL_TESTS() 매크로가 실행되면 아래와 같은 단계가 수행됩니다.

  • 현재 GoogleTest의 설정(flags)을 저장
  • 첫 테스트를 위한 테스트 고정부 객체 생성
  • SetUp()을 통해 초기화
  • 테스트 고정부 객체에서 테스트 수행
  • TearDown()을 통해 고정부 정리
  • 테스트 고정부 객체 제거
  • 저장되었던 GoogleTest의 설정으로 복원
  • 위의 과정을 다음 테스트에서도 반복, 모든 테스트를 수행할때까지 반복

위 과정에서 심각한 실패가 발생한다면, 아래 과정은 생략될 수도 있습니다.

중요
RUN_ALL_TESTS()의 반환 값을 무시하면 안됩니다. 해당 값을 무시할 경우 컴파일 에러가 발생할 수 있습니다.
자동화 테스팅 서비스에서는 stdout/stderr 출력이 아니라, 종료 코드로 전체 테스트의 성공/실패 여부를 결정하기 때문에 이렇게 설계되었습니다.
그러므로, main() 함수의 반환 값은 RUN_ALL_TESTS()의 반환 값이어야 합니다.

또한, RUN_ALL_TESTS()단 한번 호출되어야 합니다. 만약 두 번 이상 호출할 경우, GoogleTest의 일부 고급 기능과 충돌이 발생할 수 있습니다. (예를 들어 thread-safe 종료 테스트)

사용 가능 환경: Linux, Windows, Mac.

main() 함수 작성하기

대부분의 경우 굳이 main() 함수를 직접 작성할 필요가 없습니다. 대신 적절한 진입점을 정의하는 gtest_main()에 연결됩니다. 더 자세한 내용은 이 문단의 끝 부분을 읽으시면 됩니다. 이 문단의 나머지 부분은 테스트가 수행되기 전에 무언가 사용자 지정 작업이 필요하거나, 테스트 모음 혹은 테스트 고정부로 표현할수 없는 부분이 있는 경우에만 적용하십시오.

만약 main() 함수를 직접 정의한다면, 해당 함수는 RUN_ALL_TESTS()의 결과 값을 반환해야 합니다.

아래 상용구 코드를 참고하여 작성하시면 됩니다.

#include "this/package/foo.h"

#include "gtest/gtest.h"

namespace my {
namespace project {
namespace {

// The fixture for testing class Foo.
class FooTest : public ::testing::Test {
 protected:
  // You can remove any or all of the following functions if their bodies would
  // be empty.

  FooTest() {
     // You can do set-up work for each test here.
  }

  ~FooTest() override {
     // You can do clean-up work that doesn't throw exceptions here.
  }

  // If the constructor and destructor are not enough for setting up
  // and cleaning up each test, you can define the following methods:

  void SetUp() override {
     // Code here will be called immediately after the constructor (right
     // before each test).
  }

  void TearDown() override {
     // Code here will be called immediately after each test (right
     // before the destructor).
  }

  // Class members declared here can be used by all tests in the test suite
  // for Foo.
};

// Tests that the Foo::Bar() method does Abc.
TEST_F(FooTest, MethodBarDoesAbc) {
  const std::string input_filepath = "this/package/testdata/myinputfile.dat";
  const std::string output_filepath = "this/package/testdata/myoutputfile.dat";
  Foo f;
  EXPECT_EQ(f.Bar(input_filepath, output_filepath), 0);
}

// Tests that Foo does Xyz.
TEST_F(FooTest, DoesXyz) {
  // Exercises the Xyz feature of Foo.
}

}  // namespace
}  // namespace project
}  // namespace my

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

::testing::InitGoogleTest() 함수는 해당 프로그램의 명령행을 해석하여 GoogleTest의 설정 중 인식된 부분을 제거합니다. 이를 통해 사용자는 다양한 설정을 통해 테스트 프로그램의 동작을 설정할 수 있습니다. 해당 부분은 고급 사용법에서 다룹니다. 해당 함수(::testing::InitGoogleTest())는 RUN_ALL_TESTS()호출되기 전에 미리 호출해야 설정이 적용됩니다. 만약 먼저 호출되지 않는다면 의도한 대로 초기화되지 않을 것입니다.

Windows에서는 InitGoogleTest() 함수가 확장 문자열을 지원합니다. 즉, UNICODE 환경으로 컴파일된 프로그램에서도 사용할 수 있습니다.

어쩌면 이렇게 main()함수를 작성하는 것이 너무 귀찮다고 생각할 수도 있습니다. 저희도 귀찮다는 것에 동의하기 때문에 GoogleTest에서는 기본적인 main()함수의 구현을 제공합니다. 만약 저희가 제공하는 기본적인 구현 수준이 충분하다면 gtest_main 라이브러리를 링크함으로서 main()함수 호출 작성을 생략할 수 있습니다.

비고:
ParseGUnitFlags()함수는 InitGoogleTest()으로 대체될 예정입니다.

알려진 제약 사항

  • GoogleTest는 thread-safe하게 설계되었습니다. pthreads를 사용할 수 있는 환경에서만 구현되어있습니다. 즉, Windows같이 pthreads를 사용할 수 없는 환경에서는 두개 이상의 쓰레드가 동시에(concurrently) 단언문을 사용하는 것은 안전하지 않습니다. 대부분의 테스트에서 단언문은 메인 쓰레드에 의해 수행되기 때문에 큰 문제가 되지 않을 것입니다. 만약 이 문제를 도와줄 수 있다면, 여러분의 환경(platform)에서 필수적인 동기화 동작을 gtest-port.h에 구현해주시길 바랍니다.

번역 관련 주석 (원문에 존재하지 않음)

원문과 번역한 단어의 목록은 다음과 같습니다. (그대로 음차한 번역은 생략합니다.) 익숙하지 않은 표현이거나, 오해의 가능성이 있는 번역의 경우, 처음 해당 표현이 나온 부분에 원문을 추가로 작성했습니다.

원문번역비고
Assertion단언문Wiki에서는 표명으로 번역됨, 단언문이 더 직관적이라 생각하여 번역함
Fatal심각한치명적인으로 번역했으나, 문맥상 심각한이 더 자연스러운 것으로 판단하여 이와 같이 번역함
Predicate서술부사전에 따라 단정하다를 고려했으나, Assertion의 번역인 단언과 유사한데다, 표현의 의도가 복잡한 논리식이므로 서술부로 번역함
Test fixture테스트 고정부소프트웨어 개발자 테스팅의 번역을 인용함
Test suite테스트 모음같은 설계를 가지면서 값을 공유할 수 있는 프로그램의 집합의 의미에서 모음으로 번역함
Wide string확장 문자열Wiki의 확장 문자문서를 참고하여 번역함

JaeSang Yoo
글쓴이
JaeSang Yoo
The Programmer

목차