gtest はC++のコードをテストするフレームワークである.あるクラスの単体テストにおいて,プライベートな変数の値やメソッドのチェックをgtestで行う一つの方法についてメモっておく.

レポジトリはここ に作った.

テスト用のフレンドクラス

単体テストを行うことを見越して以下のようなクラスBinaryCalculatorTestFriendを宣言しておく.

class BinaryCalculator {
public:
  BinaryCalculator() {}
  ~BinaryCalculator() {}
  inline void setArg1(int arg) { arg1_ = arg;}
  inline void setArg2(int arg) { arg2_ = arg;}
  void plus() { ans_ = arg1_ + arg2_; }
  void minus() { ans_ = arg1_ - arg2_; }
  void calc(std::function<int(int, int)> op) { ans_ = op(arg1_, arg2_); }

private:
  int arg1_ = -1;
  int arg2_ = -1;
  int ans_ = -1;

#ifdef UTEST
public:
  friend class BinaryCalculatorTestFriend;
#endif
};

このフレンドクラスはプライベートなプロパティにアクセスできてしまうため,単体テスト用のビルド時のみ-DUTESTを有効にすればよい.

gtestからアクセスする

以下のようにフレンドクラスを定義する.

#include "BinaryCalculator.h" // includes the above definition
#include "gtest/gtest.h"

class BinaryCalculatorTestFriend : public ::testing::Test {
public:
  int GetAns(BinaryCalculator &calculator){
    return calculator.ans_;
  }
};

これでプライベート変数の値を確認することができる.

TEST_F(BinaryCalculatorTestFriend, test_calc){
  BinaryCalculator calculator;
  calculator.setArg1(1);
  calculator.setArg2(2);

  // test plus
  calculator.plus();
  ASSERT_EQ(GetAns(calculator), 1+2);
  
  // test minus
  calculator.minus();
  ASSERT_EQ(GetAns(calculator), 1-2);
  
  auto squared = [](int a, int b){ return a * a + b * b; };
  calculator.calc(squqred);
  ASSERT_EQ(GetAns(calculator), 1*1+2*2);
}

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