C/C++のユニットテストフレームワーク CppUTest が便利

cpputest

今回はC/C++のユニットテストフレームワークのひとつである CppUTest について調べてみました。TDDと相性が良いと言われている Google Test と比較して、CppUTest はマルチプラットフォーム対応がより充実しているためWeb系に限らず組み込み系などでも幅広く使われているとのことです。

参考: テスト駆動開発による組み込みプログラミング ―C言語とオブジェクト指向で学ぶアジャイルな設計

これまで不満はありつつも使い慣れているからという理由で CppUnit をずっと使っていたのですが、最近は業務でC++ライブラリを作る機会が増えてきたこともあり、より効率良く仕事を進めるために新しいツールを使ってみようという気になりました。

環境

CentOS 6.4 (x86_64)
GCC 4.4.7
CppUTest 3.4

インストール

Debian系なら apt-get install cpputest でOKなのですが、Redhat系だとrpmパッケージはない(? みたいなので、ここではソースコードをコンパイルしてインストールします。最新版のCppUTestはCMake対応しているので環境に合わせて簡単に導入することができます。もし環境にCMakeが入っていなければyumで2.8系を入れておきます。

CMakeのインストール

CppUTestのインストール

GCC 4.4系だとC++11サポートフラグは効かないようなので外しています。まぁ実務でC++11を使わせてもらえるような環境ってまだあまりないと思いますが。

glibc-staticのインストール

CentOS 6.x系だとGCCでスタティックリンクするためには glibc-static を別途インストールする必要があるので注意してください。5.x系では不要です。

Getting Started

簡単なアフィン変換行列のクラスを作ってテストを書いてみます。

* geom.h

* geom.cpp

* hello_cpputest.cpp
CppUTestを使ったユニットテストコードは以下のような感じになります。

テストコードの全体的な流れとしてはGoogle Testとよく似ています。CppUTestは自動テストディスカバリ機能を持っているので、CppUnitのようにいちいちテストケースを登録する必要がないので記述が非常に簡潔になります。また、各マクロ名が短いのも地味に嬉しいです。Boost Testはマクロ名が長いので書くのが面倒ですよね。

* Makefile
CPPUTEST_HOME にはCppUTestのインストールディレクトリを指定します(ここではユーザーディレクトリ以下にインストールしてある)。また、gcov関連のオプションも忘れずに指定しておきます。ここでは手でMakefileを書いていますが、CppUTestのポリシー的にマルチプラットフォーム対応を考えてCMakeなどでMakefileを生成するのが良いんでしょうね。

実行結果は以下のようになります。実行時オプションもいくつか紹介。

JUnit形式で結果を書き出してくれるのでCIツールとも相性が良いです。ついでにカバレッジ計測も。

geom_gcov

アサーションマクロ

公式マニュアルには以下のマクロが定義されていると書かれていますが、CppUTestのソースコードを見てると他にもたくさんのマクロが定義されていました。詳細は CppUTest/UtestMacros.h を参照してください。例外のチェック用マクロなどもあるようです。

テスト対象のクラスが operator==() をオーバーロードしていると、CHECK_EQUALでインスタンス同士の等値比較もできます。

メモリリークの検出

CppUTestにはデフォルトでメモリリーク検出機能も付いています。普通にテストコードを走らせるだけでテストケース単位で検知してくれるようです。ためしにわざとリークするコードを書いて試してみます。

* テスト実行

setup/teardown 実行時のメモリ使用量の差分でリークを検出する実装になっていました。CppUTest側で operator new/delete をオーバーロードしているので、STLやBoostなどを使うとオーバーロード定義がコンフリクトしてしまうことがありますが、ヘッダ読み込みの順番を制御して回避できます。

ユーティリティツール

CppUTestにはシェルスクリプトで書かれた便利なツール群が付属しています。ここではその中の1つを紹介します。

* NewClass.sh
C++クラス用の .h/.cpp ファイルと対応するテストクラスファイルを生成してくれます。生成されるコードのスタイル等はテンプレートを定義することができます。各テンプレートファイルは $(CPPUTEST_HOME)/scripts/templates 以下にあります。

こういうコードジェネレータ系のユーティリティツールって最近はRuby製のものが多いですけど、全てシェルスクリプトで書かれているのを見るとマルチプラットフォーム対応を強く意識しているのがわかりますね。

感想

今まで使っていたCppUnitを比較すると、面倒な手順を踏まなくても簡単にテストコードを追加できるし、自動テストディスカバリ機能のおかげでテストランナーの記述が非常に簡潔になるのでTDDと相性が良いと感じました。軽快で実行効率にも優れているので組み込み系で実績があるのも納得できます。各プラットフォーム依存の実装は $(CPPUTEST_HOME)/src/Platform 以下にあるのでそれぞれ読み比べてみるのも面白いです。

あと、今回は試していませんがCppUTestはモックもサポートしています。サンプルを見る限りけっこう抽象化されていて使いやすそうです。

これからはCppUTestを使ってTDDで効率よく開発していきたいと思います。

あわせて読む:

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です