C
googletest

1分で実行できる?インストール不要、C言語向けGoogleTestサンプル for Linux

More than 1 year has passed since last update.

先にタイトルに誇大な表現があることを謝っておきます。。。

http://qiita.com/igayu/items/eaa63d017e0590504999

でC開発者向けのGoogleTestの良いところを述べたつもりですが、じゃあ次は実際に動かしてみようよ、って時の手ごろなサンプルを用意してみました。GoogleTest自体がサンプルコードも提供しているみたいですが、慣れてないとビルド方法とか、英語だから読む気しない、って人もいます。それくらい常識、勉強しなさい、と切り捨てると仕事は回りません。せっかくGoogleTest、便利そうだね、って思ってくれた人にはもう少し背中を押してあげます。

ここで紹介するサンプルは以下の前提で書いています。

・C言語開発者向けということでC++の文法には極力触れない

・Linux gccベース(私はWindows7にvmwareでCentOS6.7を仮想OSとして使用)
・私が考えるGoogleTestの最低限重要なエッセンスを残す(次のステップは別記事で書こうと思う)
・超素人向けではないがLinuxやCの基本知識を持っている人なら十分理解できる難易度のつもり


下準備

・GoogleTestは入手してzip展開しておいてください

https://github.com/google/googletest/releases

からgoogletest-release-1.8.0.zipを今回は使用する(執筆時点での最新版)。

・空のファイルとしてtarget.c, target.h, test.cpp, Makefileを作っておく。

まとめると以下のような構成です。

C:\Users\xxx\Desktop\gtestSample

googletest-release-1.8.0 (ディレクトリ)
Makefile (空ファイル)
target.c (空ファイル)
target.h (空ファイル)
test.cpp (空ファイル)

サンプルコードを載せるので空ファイルにそれをそのままコピペしてmakeして動かしてね、ということをやります。あなたが人に薦める立場ならあなたが上記の構成を作って動くようにしておいて、その環境を他人に触らせる、というやり方が良いと思います。


ファイルを作成する

以下のtarget.c, target.c, target.h, test.cpp, Makefileの内容をそれぞれ作成した空のファイルにコピーしてください。


target.c

// テスト対象関数

// 0を入れたら0、それ以外は1を返す
int function(int a){
if (a == 0){
return 0;
} else {
return 1;
}
}


target.h

// テスト対象関数のプロトタイプ宣言

#ifndef _TARGET_H_
#define _TARGET_H_

int function(int a);

#endif /* _TARGET_H_ */



test.cpp

// テストケース記述ファイル

#include "gtest/gtest.h" // googleTestを使用するおまじないはこれだけでOK
// テスト対象関数を呼び出せるようにするのだが
// extern "C"がないとCと解釈されない、意外とハマりがち。
extern "C" {
#include "target.h"
}

// fixtureNameはテストケース群をまとめるグループ名と考えればよい、任意の文字列
// それ以外のclass~testing::Testまではおまじないと考える
class fixtureName : public ::testing::Test {
protected:
// fixtureNameでグループ化されたテストケースはそれぞれのテストケース実行前に
// この関数を呼ぶ。共通の初期化処理を入れておくとテストコードがすっきりする
virtual void SetUp(){
}
// SetUpと同様にテストケース実行後に呼ばれる関数。共通後始末を記述する。
virtual void TearDown(){
}
};

// 成功するテストケース。細かい説明はGoogleTestのマニュアルを見てね。
TEST_F(fixtureName, testOk)
{
EXPECT_EQ(0, function(0));
EXPECT_EQ(1, function(100));
}
// あえて失敗するテストケースも書いておく。
TEST_F(fixtureName, testNg)
{
EXPECT_EQ(1, function(0));
EXPECT_EQ(0, function(100));
}


# Makefile

# all:より下の3行のインデント、
# gtest-gen:より下の1行のインデント
# は半角空白になっていますがタブ1個にしてください
# target.cはCなのでgccで、それ以外はC++なのでg++でビルドします
# gtest_main.ccはGoogleTestが用意してくれているmain関数、
# gtest-all.ccがGoogleTest全部入りファイルです
# -lpthreadをつけることにも注意。
# makeかmake allしたらビルドして実行まで行います。
all:
gcc -c target.c
g++ test.cpp googletest-release-1.8.0/googletest/src/gtest_main.cc gtest/gtest-all.cc -I. -lpthread target.o
./a.out

gtest-gen:
python googletest-release-1.8.0/googletest/scripts/fuse_gtest_files.py ./


GoogleTestのインストール(に代わるもの)

準備段階ではWindowsPCでこしらえてもよいですがここからはLinuxでの作業が前提。

cd <サンプルがあるディレクトリ>/gtestSample

make gtest-gen

gtestSample/gtestに幾つかファイルが吐き出されます。何をやっているかというとMakefileにある通りpython googletest-release-1.8.0/googletest/scripts/fuse_gtest_files.py ./にある通り、fuse_gtest_files.pyを実行して出力結果をカレントディレクトリ./に吐き出させます(もしかするとpythonの有無・バージョンとかでハマることがあるかもしれません)。何が出来上がるかは後で観てみてください。GoogleTestの機能を全部詰め込んだ巨大なCファイルが出来るのでライブラリ化せず自分のテストコードと一緒にコンパイル出来るのです。

これは私が強くGoogleTestをオススメする動機の1つです。rootでmake installも不要ですし、この人のPCにはインストールされているけどこの人のPCだとテストが動かない、といったことが無くなります。


実行

cd <サンプルがあるディレクトリ>/gtestSample

make

以上です。2つテストケースが実行されて1つがPASS、1つがNGになるはずです(Makefileのコメントに書きましたが空白をタブに置換するのを忘れないでください)。

ログの見方は特に説明しなくても直感的にわかるかと思います。


こだわり

テストケースはTEST()で記述してもいいのですが敢えてTEST_F()だけでテストケースを記述します。経験上ある機能のテストが1個のテストケースで済むことはなく、2個以上のテストケースを作るとかなりの確率で共通の前処理・後処理が出来ます。またTEST()とTEST_F()が混在しているテストコードは見づらいと思います。なので私のチームではTEST_F()だけを使うようにしています。


最後に

下準備は除き、ファイル作成から実行まで慣れれば1分切れると思います!(=`ェ´=)ゞ

このサンプルをベースにGoogleTestの使える機能を足していく(たとえばテストケースの一時無効化とか)ことにしますが筆不精なのでまたいつか…