C++ - Google Test/Mock 기능 정리

원문

매크로

TEST(), TEST_F(),TEST_P()

https://github.com/google/googletest/blob/master/googletest/docs/primer.md#simple-tests

TEST(TestSuiteName, TestName) {
  ... test body ...
}
  • 테스트 케이스의 대 항목dls 이름과 소항목인 이름을 입력한다.
    • 여러 테스트가 있는 경우는 대 항목 이름과 소항목 이름의 조합이 중복되지 않도록 하지 않으면 빌드 오류가 발생한다.
  • TEST_F에서 첫 번째 인수는 테스트 픽처로 정의된 클래스 이름으로 한다.
  • TEST_P는 고급 기술로 하나의 테스트 매개 변수를 바꿔가면서 여러 번 수행 할 수 있다.
    • http://opencv.jp/googletestdocs/advancedguide.html#adv-how-to-write-value-parameterized-tests

ASSERT_EQ, EXPECT_EQ

http://opencv.jp/googletestdocs/primer.html#primer-binary-comparison

  • 첫 번째 인수가 기대 값, 둘째 인수가 실제 값. 함수를 실행했을 때 반환 체크 등에 사용할 수 있습니다.
  • EXPECT_NE나 EXPECT_TRUE같은 친척도 있습니다
  • 상황이 예상과 다른 경우 즉시 테스트가 종료되는 것이 ASSERT_계속하는 것이 EXPECT_있습니다.

MOCK_METHOD, MOCK_CONST_METHOD

  • mock 메소드의 정의에 사용한다. * 부분은 인수의 수이다.
    • 인수의 수는 10을 넘으면 죽는다. 인수가 많은 함수가 많은 프로젝트에서는 대책이 필요하다.

EXPECT_CALL

  • Mock의 메소드가 호출되는 것을 선언한다. 첫 번째 인수가 Mock화된 클래스의 인스턴스(포인터가 아닌 실체), 두 번째 인수가 메소드 이름
    • 메소드 이름은 인수를 세트로 지정한다. 인수가 일치하지 않는 호출된 경우는 호출 되지 않는다.
    • 아래의 ::testing::_를 사용해서 인수의 체크를 없애준다
  • 아래의 NiceMock이 아닌 경우, EXPECT 되지 않은 Mock 메소드 호출은 경고된다.(테스트는 성공하기도 한다). EXPECT한 호출이 아니었다면 테스트는 실패한다.

::testing::_

https://github.com/google/googletest/blob/master/googlemock/docs/cheat_sheet.md#wildcard

  • 정확한 정의로는 Matcher의 wildcard이며, 이 이름대로 임의의 인수를 허용한다
  • Matcher는 위의 페이지에 여러 있으므로 봐두면 도움이 될듯

Times

http://opencv.jp/googlemockdocs/fordummies.html#cardinalities

  • EXPECT_CALL 멤버와 비슷한 형태로 사용하고 호출 횟수를 지정할 수 있다. cardinality(기수)라고 한다.
  • ::testing::AtLeast(n)(n은 0 이상의 정수)로 횟수 체크를 느슨하게 할 수 있다
  • 지정된 횟수까지 호출하지 않으면 테스트가 실패한다
  • Times(0)로 함으로써 이 메소드가 호출되지 않음을 선언 할 수 있다
  • Times(1)은 생략 할 수 있다.

WillOnce, WillRepeatedly

http://opencv.jp/googlemockdocs/fordummies.html#fordummies-general-syntax

  • EXPECT_CALL 멤버 형태로 사용하고, 호출 할 때의 action을 정의 할 수 있다
    • action은 주로 반환 값 지정이다. 반환 값이 없는 메서드는 이것은 할 수 없다.
  • Will**Times의 뒤에 써야 한다.
  • WillOnce는 여러 번 사용할 수 있으며 이때마다의 반환 값을 action을 바꿀 수 있다.
using ::testing::Return;...
EXPECT_CALL(turtle, GetX())
    .Times(5)
    .WillOnce(Return(100))
    .WillOnce(Return(150))
    .WillRepeatedly(Return(200));

::testing::Return

https://github.com/google/googletest/blob/master/googlemock/docs/cheat_sheet.md#actions-actionlist

  • 위의 Will**의 action으로 값을 반환하는 동작을한다
  • action도 위의 페이지처럼 여러 종류가 있다.

RetiresOnSaturation

http://opencv.jp/googlemockdocs/fordummies.html#expectation-sticky

  • EXPECT_CALL 멤버 형태로 사용하고, 이 EXPECT_CALL의 역할이 끝나면 더 이상 EXPECT_CALL를 보이지 않도록 지정할 수 있다.

    Google Mock의 Expectation가 default로는 “sticky”임을 나타낸다

::testing::Invoke

http://opencv.jp/googlemockdocs/cheatsheet.html#cheatsheet-using-afunction-or-functor

  • 아래와 같이 함수를 action으로 정의 할 수 있다. mock 대신 fake적인 사용법이다.
    double Distance(Unused, double x, double y) { return sqrt(x*x + y*y); }
    ...
    EXPECT_CALL(mock, Foo("Hi", _, _)).WillOnce(Invoke(Distance));
    
  • action에 Invoke로 등록하는 함수는 Mock의 메소드와 같은 함수의 형태(또는 void *와 같은 호환성 이있는 어떤 타입이어야한다.
    • 사용하지 않는 인수는 Unused로 할 수 있다. 위의 예에서도 사용하고 있다.
  • InvokeWithoutArgs도 있는 것 같다. 이것은 인수를받지 않는 대신 일체의 인수를 무시할 수 있다.

NiceMock<>

http://opencv.jp/googlemockdocs/cookbook.html#nice-strict

  • 이것으로 선언된 Mock은 이 Mock 메소드가 EXPECT_CALL로 설정되기 전에 호출되어도 Assert 등을 발행하지 않는다.
    • “우선 EXPECT_CALL을 명시하고 mock의 동작을 지정하자”
    • “매우 신중하게 이용해야 한다” “버그가 경고되지 않고 간과 될 수 있다”
    • 아무래도 좋다 클래스에서만 사용할 수 있도록 하는 것을 저도 추천한다
  • 친척인 StrictMock도 있다.

문법적인 것

테스트 픽쳐

https://github.com/google/googletest/blob/master/googletest/docs/primer.md#test-fixtures-using-the-same-data-configuration-for-multiple-tests

  • ::testing::Test에서 파생된 클래스를 정의하고 픽쳐를 만들 수 있다.
  • 구체적으로는 픽처에서 만든 인스턴스를 테스트 케이스 간에 공유하거나 할 수 있다.

RUN_ALL_TESTS와 main 함수

http://opencv.jp/googletestdocs/primer.html#primer-invoking-the-tests
http://opencv.jp/googlemockdocs/fordummies.html#fordummies-using-mocks-in-tests

  • 픽처 및 mock를 사용하는 경우에는 초기화로 main()가 필요하다.
  • main()을 준비한 경우는 main()의 return으로 RUN_ALL_TESTS()을 실행하게 하면 좋을 것 같다.
    • RUN_ALL_TESTS에서 모든 테스트를 실행한다. 이때 Setup()와 TearDown()가 각 테스트마다 실행되는 것에 주의가 필요한다.

::testing::InitGoogleMock

Mock을 사용하는 경우 초기화를 하도록 한다.

여러 Exception ( EXPECT_CALL)

http://opencv.jp/googlemockdocs/fordummies.html#fordummies-using-multiple-expectations

  • 여러 matcher(match 조건)에 대한 EXPECT_CALL을 미리 써둘 수 있다.
EXPECT_CALL(turtle, Forward(_));  // #1
EXPECT_CALL(turtle, Forward(10))  // #2
    .Times(2);
  • 그러나 여러 Exception은 독특한 동작을 하므로 테스트에 고생 할 수 있다 :
    • Match의 판정은 마지막에 정의된 순서로 하는 것 같다
    • 같은 matcher 대해 여러 EXPECT_CALL을 작성하고 마지막으로 선언한 것으로 덮어 쓰거나한다다
  • 같은 Match 조건에서 여러 동작을 시키고 싶은 경우는 WillOnce을 여러번 켜고, ::testing::Invoke을 사용한다

InSequence

http://opencv.jp/googlemockdocs/fordummies.html#fordummies-ordered-vs-unordered

  • 메소드의 호출 순서를 확인할 수 있다
  • 또 다른 예는 EXPECT_CALL에 붙인 순서를 정의하는 방법도 써 있다.
  • 순서와 관련하여 After 라고 한다.

ON_CALL과 기본 action

http://opencv.jp/googlemockdocs/cheatsheet.html#action

  • ON_CALL에서 메소드의 default action을 지정하는 것이다
  • Times 미지정되지 않은 WillRepeatedly에서도 같은 것을 할 수 있지만 ON_CALL를 사용하는 것이 본래의 단계이다
    • DefaultValue::Set(value)라는 것도 있는 것 같다.

이 글은 2020-04-30에 작성되었습니다.