自動テスト:CppUnitをVisual-C++で使う
九州オンラインソフトウェア研究会 第二回研究会 発表資料 By 古原伸介
1 エクストリームプログラミング
いくつかの経験的プログラミング手法をまとめた開発手法。
いいプログラミング手法なら極限まで適用する。
例:
コードレビューが良いなら常にコードレビュー状態でコーディングする→ペアプログラミング
特徴としては、オブジェクト指向の発展の成果を手法に取り入れている。
例:
変更がきくプログロム→詳細な初期設計をしない(常に顧客の要望は変化する)
可読性の高いソース→ドキュメントなし
2 テストの有効性
エクストリームプログラミングの中ではテストの重要性が強調されている。
・テストの自動化(プログラム化)
・コードを書く前にテストを作る
・ テストは蓄積され、常に全テストを行う→コード変更に強くなる
3 CppUnitとは?
エクストリームプログラミングで示された自動テスト(単体テスト)を実行するためのC++用クラスライブラリ。これ以外にもJava用のJUnit、VisualBasic用のVBUnitなどがある。
4 MFCでの利用法
書籍「eXtreme Programmingテスト技法」においてはさまざまなxUnitのテストが紹介されているが、MFC用はない(VC++のコンソールアプリケーション用はある)。
本家のCppUnitには、MFC用の便利な機能があるので、それを紹介する。
4-1.基本的なテスト方法
■TestCaseを書く
TestCaseクラスを継承し、テスト用のクラスを作る。
そして、テスト用の関数を追加する。
class MyTestCase : public TestCase
{
public:
MyTestCase (std::string name) : TestCase (name) {}
void setUp ();
static Test *suite ();
protected:
void testMyTest1 ();
void testMyTest2 ();
};
// クラス実装
void MyTestCase::setUp ()
{
}
void MyTestCase::testMyTest1 ()
{
MyClass obj;
assert( obj.add(1,2) == 3 );
}
void MyTestCase::testMyTest2 ()
{
MyClass obj;
assert( obj.sub(3,1) == 2 );
}
// 作成したテスト関数を suite 関数で追加する
Test *MyTestCase::suite ()
{
TestSuite *testSuite = new TestSuite ("MyTestCase");
testSuite->addTest (new TestCaller <MyTestCase> ("Test1", testMyTest1));
testSuite->addTest (new TestCaller <MyTestCase> ("Test2", testMyTest2));
return testSuite;
}
■TestRunnerでテスト
TestRunner画面を出し、Runを押すと登録されたテストが全て実行される。実行された結果、一つでも失敗があるとバーが赤で表示され、全て成功すると緑になる。
4-2.CppUnitを利用するための方法
■ダウンロード
以下より、「C++ Ver1.5」をダウンロード(CppUnitとあるのはUNIX用なので注意)。
http://www.xprogramming.com/software.htm
ダウンロードしたCppUnit15.zipを解凍する。
■ビルド
ダウンロードしたものはソースのみなのでビルドが必要になる。以下のフォルダにあるプロジェクトをこの順番でビルドする。
1.CppUnit\ms\culib
2.CppUnit\ms\TestRunner
必須ではないが、サンプルとして、CppUnit\ms\HostApp もビルドして試してみる。
■プロジェクトへの組込
(1) リンク
culib.lib testrunner.lib をリンクするようにする。
(2) インクルード
以下にインクルードパスを設定する。
CppUnit\test\framework
CppUnit\test\framework\extensions
CppUnit\ms\TestRunner
■テストトケースを作る
CppUnit\samples にある ExampleTestCase.h と ExampleTestCase.cpp を参考に、テストケースを書く。
■TestRunnerの呼び出し
CMainFrameクラスでTestRunnerを呼び出す例:
// 必要ファイルをインクルード
#ifdef _DEBUG
#include "MyTestCase.h"
#include "TestRunnerDlg.h"
static AFX_EXTENSION_MODULE extTestRunner;
#endif
// デバッグ時のみ、メニューに現れるようにする
void CMainFrame::OnInitMenu(CMenu* pMenu)
{
CMDIFrameWnd::OnInitMenu(pMenu);
#ifdef _DEBUG
static bool first=true; // 1回しか追加しないように
if( first ){
first=false;
CMenu* pMainMenu = GetMenu();
CMenu* pSubMenu = pMainMenu->GetSubMenu(0);
pSubMenu->AppendMenu(MF_STRING,ID_TEST_RUN ,"テスト実行" );
}
#endif
}
// TestRunnerを出す
void CMainFrame::OnTestRun()
{
// TODO: この位置にコマンド ハンドラ用のコードを追加してください
#ifdef _DEBUG
TestRunner runner;
runner.addTest (MyTestCase::suite ());
runner.run ();
#endif
}
■注意点
・RTTIを有効にしておく([プロジェクト]-[設定]の「C/C++」の「C++言語」)。
・「共有DLLでMFCを使用」でのみ利用可能(デバッグは共有にしておけばよい)。