【C/C++】単体テストのすすめ(gtest)


目次

  1. gtestとは
  2. gtest環境構築
    1. 事前準備
    2. gtestのビルド&インストール
  3. gtest使い方の例
    1. テストコードのサンプル
    2. テストコードのコンパイル
  4. エラー&解決方法のメモ


1.gtestとは

gtest(正式にはgoogletest)はC++の単体テストフレームワークです。

・導入が簡単
・機能が豊富
・テストコードが書きやすい

と三拍子揃っているので、個人的にはC++のテストフレームワークの中では一番気に入っています。

単体テストに以下を求める人に特にオススメです。
・充実した日本語ドキュメント
・モック・スタブの機能
・フリーで使用したい(gtestは三条項BSDライセンスです)

上の内容がイマイチしっくりこない方はwikipediaに色々なunittestが一通り載っているので自分にあったunittestを探してみるのもいいかもしれません。
wikipedia-ユニットテスト・フレームワーク一覧#C++

この記事では以降gtestについて書いていきます。


2.gtest環境構築

※今回の環境構築はmacOS Catalina 10.15.4で行いました。
 Unix系は大体同じだと思いますが。


2-A 事前準備

gtestをインストールするためには、以下が必要です。
・CMake
・C++11以上に対応したコンパイラ

(C/C++書いてる人なら既にインストール済かもしれませんが…)

C/C++の開発環境構築を以前まとめたので(https://www.mathkuro.com/?p=235)、こちらを参考に準備していただければと思います。

(macOS, CentOS, Ubuntuは↑の記事でOKですが、windowsの章はCMakeに触れてないです。すいません。今度追加しておきます。)


2-B gtestのビルド&インストール

まず、googletestをgithubからcloneします。
(ディレクトリはどこでも良いです。)
$ git clone https://github.com/google/googletest.git

cloneしたgoogletestの中にビルド用のディレクトリを作成します。
$ mkdir -p ./googletest/mybuild

作成したビルド用ディレクトリに移動します。
$ cd ./googletest/mybuild/

cmakeを実行し、makefile等を作成します。
$ cmake -DCMAKE_CXX_FLAGS="-std=c++11" ..

makeを実行し、gtestをビルドします。
$ make

以下が出力されればビルド完了です。

[100%] Built target gtest_main


最後にgtestのインストールを行います。
※実行すると/usr/localの下にインストールされます。
$ make install

これで、googletestのインストールは完了です。
※ビルドに使用したディレクトリ等は使用しないので削除しても大丈夫です。


3.gtest使い方の例

ここでは、簡単なテストコードとコンパイル例を紹介します。

3-A テストコードのサンプル

// インクルード
include "gtest/gtest.h"

// テスト対象の関数(普通は別ファイルですね)
int sum(int a, int b) {
    return a + b;
}

// TEST()マクロを使用して、テストを作成
TEST(MyTestCase, Test001) {

    // アサーションを使用してテスト
    EXPECT_EQ(3, sum(1, 2));
}

↑たったこれだけでテスト完成です。

あとはコンパイルすれば自動試験の完成です。


3-B テストコードのコンパイル

コンパイルは以下のコマンドです。
$ g++ -std=c++11 ./gtest_sample.cxx -lgtest_main -lgtest

-lgtest_mainで、gtestデフォルトのmain関数が使えます。
これが、3-Aの例のように、テストコードが簡単な理由です。

実際にテストコードを実行すると以下の結果が得られます。

mathkuro002:unittest kuro$ ./a.out
Running main() from /Users/kuro/googletest/googletest/src/gtest_main.cc
[==========] Running 1 test from 1 test suite.
[———-] Global test environment set-up.
[———-] 1 test from MyTestCase
[ RUN ] MyTestCase.Test001
[ OK ] MyTestCase.Test001 (0 ms)
[———-] 1 test from MyTestCase (0 ms total)

[———-] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[ PASSED ] 1 test.
mathkuro002:unittest kuro$

テストの実行数・OK/NG数、NGの場合はそのNGの原因が表示されます。


このように、googletestを使うのはとても簡単なのです。
C/C++で自動試験を作りたいなーと考えている方は是非一度試してみてください。

本文は以上です。

↓ここから下はエラーが起きた際の試行錯誤のメモです↓


4.エラー&解決方法のメモ

その1

cmake→makeを行った際に以下のエラー(一部抜粋)が発生しました。

/Users/kuro/googletest/googletest/include/gtest/internal/gtest-port.h:844:12: error:
no member named ‘make_tuple’ in namespace ‘std’
using std::make_tuple;
~^

〜〜(中略)〜〜

/Users/kuro/googletest/googletest/include/gtest/internal/gtest-port.h:679:35: note:
expanded from macro ‘GTEST_DISALLOW_ASSIGN_’
type& operator=(type const &) = delete
^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
make[2]: *** [googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o] Error 1
make[1]: *** [googletest/CMakeFiles/gtest.dir/all] Error 2
make: *** [all] Error 2

cmake実行時にc++11のフラグをつけていないことが原因でした。

以下のようにc++11を明示してcmakeを実行すればOKです。
$ cmake -DCMAKE_CXX_FLAGS="-std=c++11" ..


その2

自分で作成したテストコードのコンパイル時に以下のエラーが発生しました。

Undefined symbols for architecture x86_64:
“testing::AssertionSuccess()”, referenced from:
testing::AssertionResult testing::internal::CmpHelperEQ(char const, char const, int const&, int const&) in gtest_sample-89dce9.o

“typeinfo for testing::Test”, referenced from:
typeinfo for MyTestCase_Test001_Test in gtest_sample-6319ee.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

これは静的ライブラリのリンクができていなかったためでした。
$ g++ -std=c++11 ./gtest_sample.cxx -lgtest_main -lgtest

今回の場合だと、-lgtest_main, -lgtestのリンクが必要でした。

参考

↓gtest全般。日本語。
http://opencv.jp/googletestdocs/primer.html

↓wikipedia。
wikipedia-ユニットテスト・フレームワーク一覧#C++

↓ビルドの参考。
https://qiita.com/y-vectorfield/items/6238cfd2d9c34aefe364

Leave a Reply

Your email address will not be published. Required fields are marked *