読者です 読者をやめる 読者になる 読者になる

プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

Google Test を使ってみた

C/C++ プログラム関連

先日、C++で開発したプログラムの単体試験を行いました。せっかくなので、なにか単体試験用のフレームワークがないか探してみると、Google Test (Google C++ Testing Framework) なんてものがありました。名前からして良さそうな雰囲気。無償だし、ちょっと調べてみると、かなり使えそう。なので、結局これを使ってお仕事の単体試験は乗り切りました。

そこで、せっかくなので忘れないうちに、このGoogle Test を使った際の使い方などを備忘録代わりにまとめておきます。

 

本記事の動作環境

なお、Google Test そのものはLinux,Windows, Mac など複数の環境で動作するようになっています。ここでは、Windows7上のVisual Studio 2010 を対象にしました。

 

インストール

Google Test のプロジェクトトップページに、まずダウンロードして、解凍して、README読めとあるのでそうします。解凍したフォルダ一式は gtest-1.7.0 というような名前のフォルダになっています(この記事の時点のバージョンが、1.7.0でした)。

README を読むとソースからこのフレームワークのライブラリをビルドしておく必要がありそうです。

Windows でかつVisual Studioの場合は、CMake を使うのが簡単そうなので、そうします(CMake が未インストールだったらこれもインストールしてやります)。

 

CMake GUI を起動して、『Where is the source code』にGoogle Test を解凍したフォルダを指定してやります。また、『Where to build the binaries』は基本的にどこでもいいのですが、わかりやすいようにここではGoogle Test を解凍したフォルダ下にbuild というディレクトリを指定します(なければこの後の処理で自動で作ってくれます)。

 

画面下部のConfigureボタンを押すと、ディレクトリを作成するか?、とかVisual Studioのバージョンとかを聞かれるので、それに答えてやります。

 

問題がなければ、画面下部にConfiguring done と表示されます。

 

続けて、Generate ボタンを押すとプロジェクトの生成が始まり、問題がなければ画面下部にGenerating done と表示されます。

CMake での作業はここまでです。

 

次に、CMakeの結果、buildフォルダ(この例では、gtest-1.7.0/build)の下に、ソリューションファイルが作成されているので、これを開きます。

 

VisualStudioで開いたら、ソリューション全体をリビルドしておきます。

build/Debug または build/Release フォルダに、gtest.lib, gtest_main.lib ファイルができていればOKです。

 

サンプルプロジェクトの作成

では、テスト対象となるサンプルプログラムを作ります。今回はGoogle Test を試すための簡単なものにしておきます。

プロジェクトを、Win32コンソールアプリケーションとして作成し、2つの整数を足した答えを返す関数を作ります。また、一応、それを呼び出すmainも作っておきます。

 

myadd.h

#ifndef MYADD_H
#define MYADD_H

namespace mytest {

int myadd(const int a, const int b);

}

#endif

 

myadd.cpp

#include "myadd.h"

namespace mytest {

int myadd(const int a, const int b)
{
  return a + b;
}

}

 

myprogram.cpp(main)

#include <iostream>
#include "myadd.h"

int main(int argc, char* argv[])
{

  const int c = mytest::myadd(1,2);
  std::cout << c << std::endl;

  return 0;
}

このmyadd関数を対象に単体試験を書くことにします。

 

単体試験用プロジェクトの作成

単体試験用のプロジェクトとして、VisualStudio のプロジェクトを作ります。

プロジェクトとしてはWin32コンソールアプリケーションとします。このプロジェクトで、Google Test を使うためには、上記でビルドしたライブラリを参照するのと、includeファイルを見つけられるようにする必要があります。

 

プロジェクトのプロパティを開きます

『C/C++』の『追加のインクルードディレクトリ』に、gtest-1.7.0 を追加します。

また、ついでに試験対象の関数のヘッダファイルも見つけられるように、ここに追加しておきます。

 

『リンカー』の『追加のライブラリディレクトリ』に、gtest-1.7.0\build\Release が指定されるようにします(実際には、デバッグビルドとリリースビルドで共有できるように、$(Configuration)マクロを使っています)

 

『リンカー』のサブメニューを開いて『入力』を選択します。

『追加の依存ファイル』に、gtest.lib、gtest_main.libを指定します。


gtest_main.lib をリンクした場合は、main関数を自前で書く必要がありません。自分でテストプロジェクト用のmain関数を書きたい場合は、gtest_main.libをリンクする必要はありません(詳しくはドキュメントを参照)。

 

VisualStudio での追加設定

実は、VisualStudio の場合はこれだけではビルドを行うとLNK2005のエラーが多発する場合があります。これは、FAQのページにも載っており、Google Testライブラリを作った際のコンパイラ設定とテストプロジェクトの設定が異なっていることが原因だそうです。

 

具体的には、ランタイムライブラリのリンク方法の指定を確認します。Google Test のプロジェクトでは、/MT (リリースビルド)または/MTd (デバッグビルド)が指定されています。これはCランタイムライブラリ(以下CRTとも表記します)としてスタティックライブラリを使うということです。一方、テストプロジェクトでは、(デフォルトの場合)/MDまたは/MDdになっています。CRTとしてDLLを使うということです。

 

ここでは、テストプロジェクト側を/MTまたは/MTdに変更します。

『C/C++』のサブメニューを開いて、『コード生成』にある『ランタイムライブラリ』で、/MTまたは/MTdを選択します(リリース版かデバッグ版かで切り替えてください)。

 

もちろん、Google Test ライブラリを作成する際に、ランタイムライブラリを/MDまたは/MDd にしても問題ありません(テスト対象によることになると思います)。

 

単体試験の作成

これで、準備ができました。単体試験用のコードを作成したいと思います。記述はTESTマクロを利用して行います。マクロの第一引数がテストケース名で、第2引数がテスト名、ということです。

たとえば、こんな感じで1つのテストケース(AddTest)に対して4つのテスト(PositiveNumber, NegativeNumber, ZeroNumber, PositiveAndNegativeNumber)を記述します。

各テストはアサーションと呼ばれる期待される値を確認するマクロを記述していきます。詳細はGoogle Test のドキュメントをご覧ください。

また、一つのテストに複数の確認項目が含まれていても問題ありません。下記では、一つのPositiveNumberのテストで3回の確認を行っています。

 

myaddunittest.cpp

 

#include "gtest/gtest.h"

#include "myadd.h"

TEST(AddTest, PositiveNumber) {
  EXPECT_EQ(3,  mytest::myadd(1, 2));
  EXPECT_EQ(13, mytest::myadd(10, 3));
  EXPECT_EQ(20, mytest::myadd(9, 11));
}

TEST(AddTest, NegativeNumber) {
  EXPECT_EQ(-3,  mytest::myadd(-1, -2));
  EXPECT_EQ(-13, mytest::myadd(-10, -3));
  EXPECT_EQ(-20, mytest::myadd(-9, -11));
}

TEST(AddTest, ZeroNumber) {
  EXPECT_EQ(0, mytest::myadd(0, 0));
  EXPECT_EQ(1, mytest::myadd(1, 0));
  EXPECT_EQ(2, mytest::myadd(0, 2));
  EXPECT_EQ(-1, mytest::myadd(-1, 0));
  EXPECT_EQ(-2, mytest::myadd(-0, -2));
}

TEST(AddTest, PositiveAndNegativeNumber) {
  EXPECT_EQ(0, mytest::myadd(1, -1));
  EXPECT_EQ(1, mytest::myadd(-2, 3));
  EXPECT_EQ(2, mytest::myadd(-3, 5));
}

あと、ビルド時にテスト対象の関数の実体が必要になるので、myadd関数を含むcppファイルをプロジェクトに追加しておきます。

これで、テストプロジェクトは完成です。

 

単体試験の実行

さて、作成したテストプロジェクトを実行してみましょう。まずプロジェクトのビルドを行います。問題がなければ、ビルドは成功します。

次に、コンソールを開いて、作成したテストプロジェクトを実行します。

 テストが正常に終わった場合、

 

のように実行したテストケース(及びテスト)のうち、どれだけが期待したとおりであったかが表示されます。

 

仮に、整数の和を求めたいのに、次のように実装されていたとします。

#include "myadd.h"

namespace mytest {

int myadd(const int a, const int b)
{
  int v1 = a;
  int v2 = b;

  if (0 > v1) {
    v1 = -v1;
  }

  if (0 > v2) {
    v2 = -v2;
  }

  return v1 + v2;
}

}

入力された整数の和を返すはずが、絶対値の和を返しています。この場合、テストには失敗し、

 

のように3テストでFAILEDがあったと表示されています。あとは個々のテストを見れば、どこに問題があるかを追うことができます。

 

当然、このテストフレームワークはクラスのメソッドの単体試験等にも使えます。また、期待値の書き方もいろんなパターンがありますし、例外発生の有無を判定することもできます。

 

詳しい情報は、Google Test プロジェクトページにあるWiki をご覧ください。なお、一部のドキュメントの日本語訳が Google Test ドキュメント日本語訳 にあります。

 

使い込むといろいろと面白そうです。