[技術講座] CppUnit 入門
まず最初にプロジェクトの雛型を作ります。私は最近次のようなディレクトリ構成を好んで使っています。ヘッダファイルと実装ファイルを同じディレクトリに置き、サブディレクトリ tests に単体テストコードを置きます。
[Project Root] - README - configure - ... - dicegame/ … ソースファイル (プロジェクト名) - XXX.h - XXX.cpp - ... - tests/ … 単体テストコード - XXXTest.h - XXXTest.cpp - ... - AllTests.cpp + model/ … UML のモデル (必要に応じて) + config/ … Autoconf/Automake 関係のファイル + msvc/ … MSVC++ プロジェクトファイル
このディレクトリ構成に、以下で説明するビルド関係のファイルを加えたものを用意しました。プロジェクトの雛型としてご利用ください。
Autoconf/Automake は使用するコンパイラや使用できるライブラリ等を調べて、その差異を吸収するためのツールです。GNU の標準開発ツールであり、GNU 以外のプロジェクトでも広く使われるようになりつつあります。最近の Linux や Cygwin 等には標準でインストールされていますが、自分の環境にないようでしたら、例えば次の場所からダウンロードすることができます。
Automake は生成するターゲットとソースファイルの一覧 Makefile.am から Makefile の雛型 Makefile.in を自動生成するツール、Autoconf はどんな開発環境の違いを調べるか記述したファイル configure.in からシェルスクリプト configure を生成するためのツールです。実際の開発環境の調査はこのスクリプト configure が行い、Makefile.in から各開発環境用の Makefile を作成します。
Makefile.am configure.in | | | automake | autoconf ↓ ↓ Makefile.in configure | | | configure ←――┘ ↓ Makefile
では、実際に使ってみましょう。自分で作成するのは、プロジェクトのルートに configure.in、各ディレクトリに Makefile.am というファイルです。まずは、configure.in の内容の概要から説明します。dnl から行末まではコメントです。
configure.in
dnl ディレクトリ構成が正しいか確認する。 dnl できるだけプロジェクトに固有のファイルを指定する。 AC_INIT(dicegame/Makefile.am) dnl Autoconf 関係のファイルをサブディレクトリに置く。 AC_CONFIG_AUX_DIR(config) dnl プロジェクト名とバージョンを指定する。 AM_INIT_AUTOMAKE(dicegame, 0.1) dnl 各プログラムが使用可能か調べる。 AC_PROG_CC AC_PROG_CXX AC_PROG_RANLIB dnl 実行ファイルの拡張子を調べる (Cygwin 対応)。 dnl 次の AC_LANG_CPLUSPLUS より前に書かないと不具合発生 (Autoconf のバグ?)。 AC_EXEEXT dnl C++ が使用可能か調べる。 AC_LANG_CPLUSPLUS dnl 生成するファイルを指定する。 AC_OUTPUT(Makefile \ dicegame/Makefile \ dicegame/tests/Makefile)
続いて各ディレクトリの Makefile.am の内容を簡単に説明します。
Makefile.am
# サブディレクトリ dicegame の Makefile を実行する。 SUBDIRS = dicegame
dicegame/Makefile.am
# サブディレクトリ tests の Makefile を実行する。 SUBDIRS = . tests # ライブラリ libdicegame.a を作成する。 noinst_LIBRARIES = libdicegame.a # libdicegame.a のソースファイル。今はまだ無い。 libdicegame_a_SOURCES =
dicegame/tests/Makefile.am
# テスト時、AllTests(.exe) というファイルを実行する。 TESTS = AllTests # インクルードパスを指定する。 INCLUDES = -I$(top_srcdir) -I$(includedir) # 実行ファイル AllTests(.exe) を作成する。 noinst_PROGRAMS = AllTests # AllTests(.exe) のソースファイル。 AllTests_SOURCES = \ AllTests.cpp # AllTests(.exe) のリンク時のオプション。 AllTests_LDFLAGS = -L$(libdir) AllTests_LDADD = ../libdicegame.a -lcppunit
単体テストの雛型 dicegame/tests/AllTests.cpp も作成しておきましょう。なお、オリジナルの CppUnit (特に 1.5.2 以降) は main()
の実装のしかたが異なります。詳しくはソフトウェア添付のドキュメントをご覧ください。
dicegame/tests/AllTests.cpp
#include <cppunit/TestRunner.h> int main(int argc, char* argv[]) { /* TestRunner を生成して run() を実行する。 */ CPPUNIT::TestRunner runner; /* ここに今後テストを追加していく。 */ return runner.run(argc, argv); }
ここまで準備できたら Autoconf、Automake を実行して、configure、Makefile.in を生成します。
$ mkdir config $ aclocal -I config $ autoheader $ automake --foreign --add-missing --copy $ autoconf
Autoconf、Automake 以外のコマンドも実行していますが詳細は省きます。参考文献を参照してください。プロジェクトのルートに configure、各ディレクトリに Makefile.in が生成されていれば成功です。この一連のコマンドは今後ファイルを追加するたびに実行しますので、私は次のようなシェルスクリプトを書いて使用しています。
bootstrap
#!/bin/sh set -x aclocal -I config autoheader automake --foreign --add-missing --copy autoconf$ ./bootstrap
続いて configure スクリプトを実行します。これが開発環境を調べて適切な Makefile を生成する、いわば主役のコマンドです。実行結果の例も一緒にあげておきます。いろいろなチェックをして、最後に Makefile を生成しているのがわかると思います。
$ ./configure creating cache ./config.cache checking for a BSD compatible install... /usr/bin/install -c (中略) checking for c++... c++ checking whether the C++ compiler (c++ ) works... yes checking whether the C++ compiler (c++ ) is a cross-compiler... no checking whether we are using GNU C++... yes checking whether c++ accepts -g... yes checking for ranlib... ranlib checking for a BSD compatible install... /usr/bin/install -c checking for Cygwin environment... yes checking for mingw32 environment... no checking for executable suffix... .exe updating cache ./config.cache creating ./config.status creating Makefile creating dicegame/Makefile creating dicegame/tests/Makefile creating msvc/Makefile creating config.h
では先程作成した単体テストの雛型 AllTests をビルドして、実行してみましょう。
$ make $ dicegame/tests/AllTests OK (0 tests)
と表示されれば準備完了です。
$ make check
としてもテストを実行することができます。実は Autoconf/Automake によって生成された Makefile はかなり高機能で、他にも次のような使い方が標準でできます。
# ビルドしたファイルを削除する。 $ make clean # プログラム、ライブラリをインストールする。 $ make install # 配布ファイル (XXX.tar.gz) を作成する。 $ make dist # 配布ファイルをテストする。 $ make distcheck
今回 Autoconf、Automake を Makefile を生成するためのツールとして利用しましたが、もう一つ本来の役割として、ソースコードのポータビリティをあげるツールという性格も持っています。詳しくは参考文献を見ていただけると良いのですが、個人的には C はともかく C++ の場合、ヘッダファイルにライブラリの記述 (例えば STL とか) が入ってしまうため、Autoconf で環境依存性を吸収するには config.h をヘッダでインクルードする必要があり、あまり好ましくないのではと思います。このあたり、豊富なライブラリを標準で提供している、またテンプレートを採用しなかった Java はやはり優秀だなと思います。
《参考文献・URL》
MSVC++ で CppUnit を使用する方法も簡単に紹介したいと思います。なお、それほど私は MSVC++ を使い込んでいるわけではないので、もし、間違いやもっと良い方法などありましたらどうぞご指摘ください。
3.2 の例と同じく、dicegame ディレクトリのソースファイルはいったんライブラリ dicegame.lib にまとめ、dicegame/tests にあるテストコードとリンクして dicegame_tests.exe を作成する、という方向で話を進めます。dicegame.lib の方は普通に Static Library のプロジェクトを作成すれば特に難しい点はないと思います。
続いて、dicegame_tests.exe ですが、CppUnit のヘッダファイルをインクルードし、ライブラリをリンクしなければなりません。方法としては2つあると思います。1つは [ツール>オプション] のダイアログで、インクルードディレクトリとリンクディレクトリを設定する方法です。今後 CppUnit を常用していくのであれば、ここで設定してしまうのが簡単だと思います。
もう1つの方法は [プロジェクトの設定] で個別に指定する方法です。その場合、まず CppUnit を展開したディレクトリを環境変数に設定しておくと良いと思います。
rem 設定例 set CPPUNIT_HOME=C:\Tools\cppunit-x-2001XXXX
その上で、プロジェクトのインクルードディレクトリ、リンクオプションをそれぞれ次のように設定します。
あとは、cppunit_tests.exe をビルド、実行し、
OK (0 tests)
と表示されれば準備完了です。
© 2001 OGIS-RI Co., Ltd. |
|