CUnitからGoogleTestに乗り換える際のメリット(デメリット)まとめ

#本ページの対象とする人や目的
単体テストフレームワークとしてCUnitを使っている人を対象としています。
・GoogleTestを身の回りにオススメしたい人
・GoogleTestに乗り換えたいので有用性を関係者に説明したい人
※メリットのいくつかはGoogleTest以外のテストフレームワークにも当てはまるのですがあくまでCUnit・GoogleTestの比較ということで突っ込みはご容赦ください。

CUnitよりも使いやすいテストフレームワークはないか探している人なども一応対象としていますが他ページに比べると内容は薄いと思います。GoogleTestのことはある程度分かっていて、人にどう薦めるか、に比重を置いています。

サンプルコードがあった方がイメージがつくと思うのですが、ニーズがあればアップしていきます。

#GoogleTestとは
GoogleTestはCUnitと同様、単体テストフレームワークです。
マニュアルはすべてオンラインで手に入ります(この件に関してはCUnitもマニュアルはあると思いますが)。
http://opencv.jp/googletestdocs/primer.html

こちらから1.8.0をダウンロードして使っています。
https://github.com/google/googletest/releases

#メリット
開発者目線で効果が大きいと思う順に一覧化してみました。この順に説明すればきっと使ってみたいと言われると思います。また開発者以外の人に有用性を説明する時、プロジェクト管理者目線だと「短く書ける」がテストのメンテ工数という点で、環境管理者目線だと「インストール不要」という点の方が主張すべきメリットになるかもしれません。また既存CUnit資産の活用については本ページ最後にも触れておきます。

・(たぶん)CUnitより短く書ける
・テストケースを書いたけど入れ忘れた、ということが無い
・インストールしなくても使える
・main関数不要
・テストケース一覧を出力できる
・指定したテストだけ実行できる
・テストスイート(厳密にはテストフィクスチャという)ごとにSetup, TearDown関数を用意できる
・無効化したテストはテスト実行時に「何個のテストが無効化されているよ」と明示的に表示してくれる

以降、順に説明します。

##(たぶん)CUnitより短く書ける、テストケースを書いたけど入れ忘れた、ということが無い
CUnitはテストケースを書いた後にAddSuite的な処理を入れる必要があり、
うっかり書いたけどテストされていませんでした、というミスも発生しがちです。
GoogleTestではテストケースを書いたら自動的にテスト対象に含めてくれます。

##インストールしなくても使える
全部入りCPPファイル、ヘッダを提供してくれているのでインクルードパスの設定とCPPをビルド対象に含めれば/usr/local/libなどにインストールしなくても使えます。ちょっと試してみ、とオススメする時に便利。
詳しい方法はこちらの記事(http://d.hatena.ne.jp/E_Mattsan/20120215/1329311774 )などで触れられていますがfused-srcは現在Release版には含まれておらず、以下を実施する必要がありました。
>fuse_gtest_files.py <出力先ディレクトリ>

もちろんインストールして使うこともできます。

##main関数不要
GoogleTestが用意してくれているのでビルド対象に含めるだけで使用できます。

##テストケース一覧を出力できる、指定したテストだけ実行できる
詳しくは以下を参照ください。
http://opencv.jp/googletestdocs/advancedguide.html#adv-listing-test-names
http://opencv.jp/googletestdocs/advancedguide.html#adv-running-a-subset-of-the-tests

CUnitではテストケースを定義している箇所で部分的に#if 0して散らかした経験があります。

##テストスイート(厳密にはテストフィクスチャという)ごとにSetup, TearDown関数を用意できる
詳しくは以下を参照ください。
http://opencv.jp/googletestdocs/primer.html#primer-test-fixtures

このテストスイートにあるテストケースは最初にどういう初期化するべきか、どういう後片付けをするべきか、
ということをテストスイートの宣言の中に書けるので可読性が良くなると思います。

##無効化したテストはテスト実行時に「何個のテストが無効化されているよ」と明示的に表示してくれる
詳しくは以下を参照ください。
http://opencv.jp/googletestdocs/advancedguide.html#adv-temporarily-disabling-tests

 #if 0だといつか忘れ去られてしまう可能性がある。
だけど「今は実装されていないからNGになっちゃう。けどテストは一応作っておいたから実装されたらテストしたい」という場合に
「明示的な無効テスト」にしておくとよいと思います。

#デメリット
C++の知識が必要、ただしclassを定義できることとextern "C"くらいの超初歩的な知識のみ。
くらいしか対CUnitでのデメリットは思い当たりません。

#その他
##ビルド時にはまりがちなこと
・-lpthreadの指定が必要
・cppソースをg++でなくgccでビルドしてしまっている

##どの機能を使うべきか？
便利な機能はいろいろありそうですが開発者が自由に使いすぎるとトリッキーなテストが生まれたりコントロールできない気がするので使ってよい機能、使ってはいけない機能を決めておくとよいと思います。

##過去のCUnit資産との共存をどうするか？
GoogleTestに移行したらCUnitで書いたテストケースはどうなるの？捨てるの？という質問は必ずマネージャーにされると思います。
結論から言うと工数ゼロでの流用は無理だが、機械的にちょっと直せば使用可能です。今後もテストを作るのであれば作成効率が上がった分で回収可能な投資であると説明できるでしょう。

CUnitベースのテストケース群に一部手を加える必要はあります。ニーズがあれば詳しく書きますが、やったことをメモしておきます。
###CUnitでのみ必要な部分を無効化する
main関数や、AddSuite, AddTestCase処理などを削除したり無効化する
###テストケースの関数をGoogleTestベースに書きかえる
`void testcase01(void){`
を
`TEST(testcase01){`
または
`TEST_F(testName, testcase01){`

これはテストケース数に応じて負荷は生じます。機械的な作業なのでスクリプトなどでやれそうですが、この置換作業に割くことができなければ諦めてください…

###CUnit用マクロをGoogleTestマクロに置換する
`#define CU_ASSERT  EXPECT_TRUE`
※私の関わったチームではCU_ASSERT以外のマクロは使っていませんでした。それ以外にあれば適宜GoogleTest用のマクロに変換します
###GoogleTest用のCPPファイルからCUnit用ファイルをincludeする
`#include "testCaseForCUnit.c"`
###Makefileを書き換える
GoogleTest向けに。

#最後に
ニーズあんのかな～ないんじゃないかな～と思いながら書いたのでわかりづらい点があると思います。サンプルコードくれ！とかあれば更新していきます。初投稿のためご容赦を…。