C言語でGoogle TestとGoogle Mockを使う
インストール方法
いちいち解説しない。
インストール方法からちょっと使ってみました的なTipsなんてそこらを探せばポロポロ出てくるからGoogle先生に聞いたほうが早い。というか本家見ろ。
注意点
Google Mock+Google Testを使うなら個別にビルドしないほうがいい。
Google MockのZipアーカイブを展開してさくさ生されたディレクトリ直下にGoogle Testのソースディレクトリをディレクトリ名gtestで展開してgmockをビルドする。
個別にビルドしたGMockとGtestを混在するとどうもうまく動かないので、gmockをビルドした時に使用したgtestのライブラリを使用すること。
幾つかの使い方
Getting startとかチートシートとかに載ってるけどわからない or わかりにくい、そもそも載っていないような使い方を書いておく。
Cで使う
もともとC++向けのテストフレームワークだから、Cで使おうとすると無理やりな感じになる。
例えばこんな感じのCモジュールがあったとする。
/* こんなアホなコードがあったなら削除したいが、あくまで例である。 */
#define CONSTANT_VALLUE 1
int add_constant(int v)
{
return v + CONSTANT_VALUE;
}
int add_constat(int v);
/* たまにこういうことする人がいるけどアホなのかな */
#include "sample.h"
int foo(int v)
{
return add_constant(v);
}
で、このCモジュールsample_user.cを単体テストするなら、sample.c::add_constantのmockが必要。テストコードと合わせるならこんな感じ。
#include <gmock/gmock.h>
class SampleMock {
public:
GMOCK_METHOD1(add_constant, int (int ));
};
SampleMock *mock;
extern "C" {
int add_constant(int v) {
return mock->add_constant(v);
}
class TestSampleUser : public ::testing::Test {
protected:
virtual void SetUp() {
mock = new SampleMock();
}
virtual void TearDown() {
delete mock;
}
};
TEST_F(TestSampleUser, TestFoo) {
EXPECT_CALL(*mock, add_constant(::testing::_)).WillOnce(testing::Return(2));
EXPECT_EQ(2, foo(1));
}
かっこわるいことだが、Google Mockの機能を使う必要があるため、モックした関数で使うモッククラスのオブジェクトと、テストコード中のモッククラスのオブジェクトが同じものである必要が有るため、どうしてもグローバル変数にしないとうまくいかない。
うまいやり方があるなら教えてほしい。
引数チェック
構造体渡した場合とか、ポインタ渡しした場合はあんまり書かれていない。
さっきの糞コードをちょっと改変した例
#include "sample.h"
#define CONSTANT_VALLUE 1
int add_constant(struct Value *v)
{
return v->value + CONSTANT_VALUE;
}
struct Value {
int value;
};
int add_constant(struct Value *v);
#include "sample.h"
int foo(struct Value *v)
{
return add_constant(v);
}
んでテストコード。
上のテスト対象モジュールは構造体のポインタを取る関数る。テストコードでは、与えらる引数が正しいことをチェックする必要がある。
#include <gmock/gmock.h>
#include "sample.h"
class SampleMock {
public:
GMOCK_METHOD1(add_constant, int (struct Value* ));
};
SampleMock *mock;
extern "C" {
int add_constant(struct Value *v) {
return mock->add_constant(v);
}
class TestSampleUser : public ::testing::Test {
protected:
virtual void SetUp() {
mock = new SampleMock();
}
virtual void TearDown() {
delete mock;
}
};
using ::testing::Return;
using ::testing::Pointee;
TEST_F(TestSampleUser, TestFoo) {
EXPECT_CALL(*mock, add_constant(::testing::_)).WillOnce(testing::Return(2));
EXPECT_EQ(2, foo(1));
}
雑記
インストールからGetting startやるぐらいなら読みゃわかるんですよ。READMEあるんだから。
問題は実際の使い方。そこまで書いてない記事が結構あった印象。