WindowsプログラマのWebアプリへの挑戦日記。あとパンとか。

ユニットテストの実践: CppUnitの導入(実装編)

5月 1st, 2008 Posted in C++, CppUnitの導入 | 1 Comment »

前回、CppUnitを導入しました。今回は実装編です。

本来はテストファーストで、CppUnitでテストケースを実装したあとにメインの実装を行うものなんでしょうけど、今回はすでに実装が終わったプロジェクトのユニットテストを行いました。今回作成したテストアプリはGUI版です。

まずはVCでプロジェクトを新規作成します。MFC AppWizard(exe)でダイアログベースで作成します。

[プロジェクト]-[設定]から[プロジェクトの設定]ダイアログを起動し、[C/C++]タブのカテゴリ[コード生成]で使用するランタイム ライブラリで[マルチスレッド(DLL、デバッグ)]を選択します。

同じく[C/C++]タブのカテゴリ[プロセッサ]インクルードファイルのパスに、メインのプロジェクトのパスを入力します。

[リンク]タブのカテゴリ[一般]オブジェクト・ライブラリ モジュールに、設定の対象がDebugの場合、

  1. cppunitd.lib testrunnerd.lib

Releaseの場合、

  1. cppunit.lib testrunner.lib

と入力します。

ここで、メインアプリのプロジェクトをワークスペースに追加しときます。そして[プロジェクト]-[依存関係]で、テストプロジェクトがメインプロジェクトに依存するように設定します。

テストアプリのStdAfx.hに次のincludeを記載します。

  1. #include <cppunit/ui/mfc/TestRunner.h>
  2. #include <cppunit/ui/text/TestRunner.h>
  3. #include <cppunit/extensions/TestFactoryRegistry.h>
  4. #include <cppunit/extensions/HelperMacros.h>
  5. #include <cppunit/CompilerOutputter.h>

C++アプリケーションの効率的なテスト手法(CppUnit編)なんかには、StdAfx.hは削除するとの記載がありますが、ボクの環境では削除しなくても問題ないです。てか削除するとダイアログベースのアプリなんでビルドできませんので。コンソールアプリの場合は必要ないでしょうね。

テストアプリのアプリクラス(CWinAppを継承しているクラス)のInitInstance()を次のように書き換えます。

  1. BOOL CTestApp::InitInstance()
  2. {
  3.     AfxEnableControlContainer();
  4.  
  5. #ifdef _AFXDLL
  6.     Enable3dControls();         // 共有 DLL 内で MFC を使う場合はここをコールしてください。
  7. #else
  8.     Enable3dControlsStatic();   // MFC と静的にリンクする場合はここをコールしてください。
  9. #endif
  10.  
  11.     CPPUNIT_NS::MfcUi::TestRunner runner;
  12.     runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
  13.     runner.run();
  14.  
  15.     return FALSE;
  16. }

メインプロジェクトのテスト対象となるクラスと対になるテスト用クラスを作成するのが流儀のようです。次のようなクラスを作成します。

  1. class CMainClass;
  2. class CTestClass : public CPPUNIT_NS::TestFixture  
  3. {
  4.     CPPUNIT_TEST_SUITE( CTestClass );
  5.     CPPUNIT_TEST( testFunc1 );
  6.     CPPUNIT_TEST( testFunc2 );
  7.     CPPUNIT_TEST_SUITE_END();
  8.  
  9. public:
  10.     CTestClass();
  11.     virtual ~CTestClass();
  12.  
  13.     void setUp();
  14.     void tearDown();
  15.  
  16.     void testFunc1();
  17.     void testFunc2();
  18.  
  19. private:
  20.     CMainClass* m_pApp;
  21. };

CPPUNIT_TEST_SUITEマクロとCPPUNIT_TEST_SUITE_ENDマクロの間にCPPUNIT_TESTマクロで、テスト対象となるテスト用の関数を登録します。setUp()はテスト用関数が実行される直前に呼ばれ、tearDown()はテスト終わったあとに呼ばれます。たとえばsetUp()でCMainClass* m_pAppをnewして、tearDown()でdeleteするような使い方になります。

では実装の方は、次のような感じ。

  1. CPPUNIT_TEST_SUITE_REGISTRATION( CTestClass );
  1. void CTestClass::setUp()
  2. {
  3.     m_pApp = new CMainClass();
  4. }
  5.  
  6. void CTestClass::tearDown()
  7. {
  8.     delete m_pApp;
  9. }
  10.  
  11. void CTestClass::testFunc1()
  12. {
  13.     CPPUNIT_ASSERT_EQUAL( TRUE, m_pApp->Func1( 0 ) );
  14.     CPPUNIT_ASSERT_EQUAL( FALSE, m_pApp->Func1( -1 ) );
  15. }
  16.  
  17. void CTestClass::testFunc2()
  18. {
  19.     CPPUNIT_ASSERT( m_pApp->Func2( 0 ) );
  20.     CPPUNIT_ASSERT( m_pApp->Func2( -1 ) );
  21. }

CPPUNIT_ASSERT_EQUALは、第一引数と第二引数が等しい場合にテスト成功。違ったらテスト失敗となります。CPPUNIT_ASSERTは、引数がTRUEだったらテスト成功。FALSEだったらテスト失敗となります。ほかにも、

  1. CPPUNIT_ASSERT
  2. CPPUNIT_ASSERT_MESSAGE
  3. CPPUNIT_FAIL
  4. CPPUNIT_ASSERT_EQUAL_MESSAGE
  5. CPPUNIT_ASSERT_DOUBLES_EQUAL

などあります。ここでは詳しくは省略。

さて、ここでビルドするとリンクエラーが発生します。メインプロジェクトのCMainClass::Func1()やCMainClass::Func2()にリンクできないと。ここでしばらく悩みましたが、どうやらメインプロジェクトのCMainClassのCPPファイルを、テストプロジェクトに追加しないといけないようです。なんかこれ気持ち悪いんですけど。しょうがないんですかね。

これでちゃんとビルドが通ります。

実行するとダイアログが起動され、Browseからテストケースが確認できます。通常はALL Testsを選んでおいて、Autorun at startupにチェックを入れておけば、起動と同時にすべてのテストを実行してくれるので楽です。

【関連エントリ】
ユニットテストの実践: CppUnitの導入(インストール編)

こちらもオススメ!

ユニットテストの実践: CppUnitの導入(インストール編)

4月 25th, 2008 Posted in C++, CppUnitの導入 | 3 Comments »

恥ずかしながら今までユニットテストツールを使ったことがなかったんですが、soraさんおすすめの、アジャイルプラクティス 達人プログラマに学ぶ現場開発者の習慣を読んだら、いても立ってもいられなくなり、会社の環境にCppUnitを導入しました。

CppUnitとは、C++のユニットテストを自動化してくれるステキなツールです。

導入編

導入に関しては、それほど難しくないです。ボクが今回入れた環境は、Visual C++ 6.0です。手順としては以下の通り。

CppUnitをダウンロード。実は去年の夏くらいにダウンロードしてましたが、当時は導入をあきらめてました。今回はこのときにダウンロードしたCppUnitを使いました。(cppunit-1.12.0.tar.gz)

ダウンロードしたファイルを解凍します。解凍先を\CppUnit\とします。

次のプロジェクトをVC6で開いてビルドします。

  1. \CppUnit\examples\msvc6\CppUnitTestApp\CppUnitTestApp.dsp

\CppUnit\lib以下にいろいろなDLLやらLIBやらが作成されます。ちなみにCppUnitTestAppはCppUnit自体のユニットテストです。実行するとGUIが表示されるのでいろいろいじってみましょう。

VCのメニュー[ツール]-[オプション]からオプションダイアログを開き、[ディレクトリ]タブの表示するディレクトリ[インクルードファイル]に

  1. \CppUnit\include

を、表示するディレクトリ[ライブラリファイル]に、

  1. \CppUnit\lib

を追加します。ここに設定したディレクトリはすべてのプロジェクトに適応されます。プロジェクトごとに設定したい場合は[プロジェクトの設定]ダイアログでやってください。また、次のファイルを\windows\system32の中へコピーしてください。

  1. testrunnerd.dll
  2. testrunner.dll

次回は実践編です。

【関連エントリ】
ユニットテストの実践: CppUnitの導入(実装編)

こちらもオススメ!

Windows VistaでIE6での動作確認をする

4月 20th, 2008 Posted in ローカル環境 | No Comments »

WEBサイトを作成するときに必要なのが、ブラウザごとに意図通りに表示されているかどうかの確認があります。ボクは基本的にFirefoxで確認しながら、後でIE6でちゃんと表示されるように調整するんですが、開発マシンがWindows Vistaなので、動作確認のために

  • XPマシンがある部屋に行く
  • マシンを立ち上げる
  • IE6を立ち上げて確認

ここでなにかおかしかったら、

  • Vistaマシンで修正
  • FTPでサーバへアップロード
  • XPマシンのIE6で確認

てことになり、なんだか異常なほどにめんどくさい。なんとかしようと思って、VistaマシンにVirtualBoxを入れました。

VirtualBoxというのはPC上にもう一つの仮想PCを作るソフトウェアで、VirtualBox以外にもVirtual PCとかVMwareが有名。どちらもフリーなんですけど、Virtual PCはVistaでも、

  • Windows Vista Business
  • Windows Vista Enterprise
  • Windows Vista Ultimate

にしか対応していないらしくHome Premiumなボクは断念。VMwareはなんかいろんなバージョン?があってよくわからないので、それならということでVirtualBoxをインストールしました。

インストール方法などは「VirtualBoxの使い勝手」なんかに詳しく書いてあるのでここでは省略。ゲストOSにはWindows XP HomeEditionをインストールしました。

使い始めてちょっとハマったことをメモ。

マウスが帰ってこない

ゲストOSをインストールして初めて使ったときに、ゲストOSがアクティブになったんだけどマウスがホストOSの方に帰ってきませんでした。どうやらゲストOSのウィンドウのメニュー[デバイス]-[Guest Additionsをインストール]というのでマウスの制御をする機能をインストールしないといけないみたい。でもこの段階ではホスト側にマウスが戻ってこないのでメニューを選択できません。

ゲストOS起動時などに、「ホストキーを押すとキーボードとマウスのキャプチャ状態が変更される」みたいなことが書いてあるダイアログが表示されるんだけど、これの意味がよくわからず適当にスルーしていました。このダイアログには「The host key is currently defined as Right Control.」って書いてあります。つまりホストキーは「右側のCtrlキー」ですよってこと。右側のCtrlの存在をすっかり忘れていたボクは、このことに気がつくまでわざわざゲストOSを終了させたりしていました。

  • 「右Ctrl」+ F : ゲストOSのフルスクリーンモード
  • 「右Ctrl」+ L : シームレスモード。

シームレスモードってのがステキ。これは、ゲストOSをウィンドウの中に表示するのではなくて、ゲストOSの中で起動しているアプリケーションのウィンドウががホストOS上にあるように表示されるモード。これだと、本当にVistaでIE6を動かしているような感覚で使えます。

こちらもオススメ!

素人がちょっとステキな写真を撮る方法

4月 19th, 2008 Posted in 写真, 素人がちょっとステキな写真を撮る方法 | 2 Comments »

ブログってことで情報でも発信した方がいいのかなと思いまして、ボクに何かできることがあるかなと考えたわけです。でも平凡な32歳子持ちの男にはこれといって発信できることもなく、かといって今さら日記調の記事を書く気もないなと思っておったところ、うちのヨメが言うわけですよ。

ヨメ「ママ友が遊びに来たときに、(壁に掛かっている)写真ば見てステキな写真やねぇって言いよったバイ。」

なもんでボクはこう言うのです。

ボク「こんなんちょっと気をつけて撮れば誰でも撮れるやん」

まあ壁に掛かっている写真はスパーフォトショッパーなヨメが補正したりなんだりで5割増しくらいになっているんですけどね。

じゃあってことで、そのちょっと気をつけていることを書いてみようかと思います。

まあボクはセンスなんてものは持ち合わせておりませんので、ステキなフォトグラファーな方々からすると、とんでもないことを書いたり、とんでもない写真を載せたりするかもしれませんが、優しくスルーしてくださいネ!

とにかくどっちかに寄せてみる

前置きが長くなったところで、やっと本題に入りますが、写真を撮るときにちょっと気をつけるだけで、ちょっといつもと違う写真が撮れたりするものです。撮るときにできなくても、パソコンに入れた後でちょっと手間をかけていじってやるのでももちろんOKです。

hibiki

この子はワタクシの子でして、今後たびたび登場することになります。この写真は子と公園に行ったときになにも考えずに撮った写真。

子の顔がど真ん中に来ています。こういうのを日の丸構図って言うんだと思うんですが、なんか両端が中途半端にあいててもったいない感じがします。

そこで、ちょっと画像編集ソフトでトリミング(切り取り)してみました。

hibiki

最近のデジカメは1000万画素超えてたりするので、少々トリミングしても全然問題ないネ!WEBで公開するだけなら800×600ピクセルくらいあればいいだろうし、葉書サイズに印刷するにしても300画素あれば十分だと思いますよ?ボクは。

子の顔を右に寄せてみたんですけど、なんとなくちょっとイメージ変わってますよね?

今回の写真は被写体の割合が大きい場合ですが、メインの被写体が小さいときに端っこの方に寄せるというのもボクは好きです。とにかく端っこに寄せろ!ってことです。

こちらもオススメ!
    None Found

日付データをCOleDateTimeに変換する

4月 16th, 2008 Posted in C++ | 2 Comments »

iTunesのライブラリファイル(iTunes Music Library.xml)を解析してゴニョゴニョしたいなぁと思って、VC6で解析ツールを作っています。

その中で、[2008-04-14T08:49:55Z]というgmtの書式で表される日時同士を比較したいがために、COleDateTimeに変換する関数を作りました。

値のチェックとかは省略してますよ。
言語はC++です。

  1. BOOL ConvStrToDate( LPTSTR pstrDate, COleDateTime& dateTime )
  2. {
  3.     if( !pstrDate ){
  4.         return FALSE;
  5.     }
  6.  
  7.     char sep[] = "-:TZ";
  8.     char* token = NULL;
  9.    
  10.     std::vector<std::string> vDateString;
  11.     token = strtok( pstrDate, sep );
  12.     vDateString.push_back( token );
  13.     while( token ){
  14.         token = strtok( NULL, sep );
  15.         if( token ){
  16.             vDateString.push_back( token );
  17.         }
  18.     }
  19.  
  20.     if( !vDateString.size() ){
  21.         return FALSE;
  22.     }
  23.  
  24.     char *stopstring;
  25.  
  26.     const int year = (int)strtol( vDateString[ 0 ].c_str(), &stopstring, 10 );
  27.     const int month = (int)strtol( vDateString[ 1 ].c_str(), &stopstring, 10 );
  28.     const int day = (int)strtol( vDateString[ 2 ].c_str(), &stopstring, 10 );
  29.     const int hour = (int)strtol( vDateString[ 3 ].c_str(), &stopstring, 10 );
  30.     const int min = (int)strtol( vDateString[ 4 ].c_str(), &stopstring, 10 );
  31.     const int sec = (int)strtol( vDateString[ 5 ].c_str(), &stopstring, 10 );
  32.  
  33.     dateTime.SetDateTime( year, month, day, hour, min, sec );
  34.  
  35.     return TRUE;
  36. }

なんかまずいところがあればご指摘お願いシマス!

こちらもオススメ!

Google App Engineで遊ぼうとした(続編)

4月 9th, 2008 Posted in web | No Comments »

前回の記事でGoogle App Engineで遊ぼうとしたけど、最後のアップロードで失敗しました。

原因はおそらくプロキシ経由のアップロードができないことにあると思います。家の環境でアップロードしたらすんなりと成功しました。

  1. >appcfg.py update its5055testapp

アップロードを実行すると、EmailとPasswordを聞かれるのでGmailのアドレスとパスワードを入力します。

アップロードに成功したら、http://its5055testapp.appspot.comにアクセスするとちゃんと表示されてます!!

こちらもオススメ!

Google App Engineで遊ぼうとしてみた

4月 8th, 2008 Posted in web | 6 Comments »

いつもお世話になっているsora氏よりオモローな情報をもらったので試してみようとした記録。

情報とはGoogle App Engineです。Google App Engineとは、自作のWebアプリケーションをGoogleのインフラで走らせることができるツールらしい。とにかくよくわからんので試してみることにした。

まずは、http://appengine.google.comで登録します。しばらく待ってっていうメッセージが表示されたので、しばらく待っているとgoogleからメールがきて使えますよ!って。

googleからのメールを待っている間にローカル環境にpythonを入れました。Python Programming Language — Official WebsiteのDOWNLOADのページからPython 2.5.2 Windows installerを選択してダウンロード。ダブルクリックで簡単インストール完了です。

次に、google app engineからSDKをダウンロードしておきます。Download the SDK – Google App Engine – Google CodeこちらからWindows版をダウンロードしてインストール。問題なし。

pythonとSDKの動作確認を兼ねて、コマンドプロンプトから以下を実行します。

  1. >cd "C:\Program Files\Google\google_appengine"
  2. >dev_appserver.py demos\guestbook

すると、スタートアップでdev_appserver.pyのアップデートをチェックするかとか聞かれるけど、ここは男らしくNOを選択。dev_appserver.pyってのは、pythonで作られたwebサーバーらしいです。

ブラウザで、http://localhost:8080にアクセスするとguestbookっぽいのが起動しましたヨ!
guestbook

次に、C:\Program Files\Google\google_appengineにits5055testappというフォルダを作成。その中にプログラミングの第一歩HelloWorldプログラムhelloworld.pyを作成します。

  1. #!-*- coding:utf-8 -*-
  2. print 'Content-Type: text/plain;charset=UTF-8'
  3. print ''
  4. print 'とにかく作ってみましたよ。コピペだけど。'

先頭の

  1. #!-*- coding:utf-8 -*-

は、日本語が入ったコードがGoogle App EngineでのみInternal Server Errorになる問題を回避するためにGoogle App Engineを使ってみたを参考にして(というかそのままだけど)入れています。

そして、

  1. C:\Program Files\Google\google_appengine\its5055testapp

にapp.ymlというアプリケーション設定ファイルを作成します。

  1. application: its5055testapp
  2. version: 1
  3. runtime: python
  4. api_version: 1
  5.  
  6. handlers:
  7. - url: .*
  8.   script: helloworld.py

ローカルで動作確認をします。

  1. >dev_appserver.py its5055testapp

ブラウザで、http://localhost:8080にアクセスすると、ちゃんと表示されてます!!すごい!オレ。
helloworld

http://appengine.google.com/のCreate an Applicationでアプリケーションを登録しておきます。Application Identifierは、アプリケーションのURI(http://xxxx.appspot.com/のxxxx)となるようです。Application Titleはアプリケーションのタイトルですね。そのまま。あとはなにも考えずにSaveしましたが、よかったんでしょうか。

さて、最後にローカルで作ったアプリをGoogle App Engineにアップロードします。コマンドプロンプトから次を実行します。

  1. >appcfg.py update its5055testapp

んが!アップロードに失敗しました。なんで?

もしかしたらプロキシとかのアレがアレだったりするかもしれないので、家に帰ってやってみます。

こちらもオススメ!

昼間に飲むときに気をつけたい5つのこと

4月 7th, 2008 Posted in ライフ | 2 Comments »

昼間に飲むときに気をつけたい5つのこと

九州地方は先週末サクラが満開になって、花見のクライマックスを迎えたわけですが、ボクもたまには外に出ようと思って、昨日は昼間からブルジョワな友達家族の一軒家にお呼ばれして、強風の中バーベキューで肉を食いました。

若いときは昼間から夜中まで飲み続けて食べ続けても全然へっちゃらだったのに、30歳過ぎたあたりからめっきりお酒も弱くなり、バーベキューでもちょっと肉食べただけでうっぷとなるようになりました。

それでも春先のバーベキューという雰囲気でついつい飲み過ぎ、食い過ぎてしまうんですよね。おかげで昨夜は帰宅後リバースしました。

お酒が弱いボクの経験では、昼間からビールを飲むと必ず頭が痛くなるんですが、昼間の飲酒による悪酔いを防止する方法を考えてみました。自分用メモです。

  • 飲む前に飲む

    これは昼間に限ったことではないですが、お酒を飲む前に「ウコンの力」を飲むとなんか調子いいみたいです。

  • あんまり食べ過ぎない

    酔っぱらってるとよくかまないで飲み込むのと、短時間に食べるのとで、お腹いっぱいと感じる前に大量に食べてしまいます。なもんで気がついたときにはお腹いっぱいを通り越して、気持ち悪くなってます。よくかんでゆっくり食べましょう。ダイエットの基本です。

  • 水分を摂る

    特に吸収がはやいスポーツドリンクがいいらしいです。お酒を飲むと利尿作用が働いて体から水分が排出されます。でもここで、お腹いっぱいだと水を飲む余裕もないですね。

  • 早めにソフトドリンクに切り替える

    昼間に飲む場合、例えば12時から飲み始めたとして18時まで飲んでも6時間。普通夜飲む場合は、3,4時間程度なので昼間の方が長時間飲むことになります。長く飲むとそれだけ多くアルコールが体内に蓄積されるので、早めにソフトドリンクに切り替えるといいと思います。

  • 前の日早く寝る

    お酒を飲むと眠くなる体質なんですが、飲み始めてだいたい3時間くらいで睡魔が襲ってくるようです。ボクの場合。夜飲む場合はそろそろお開きの頃に眠たくなるからいいんですが、昼間はこれからってときにどうしようもなく目が閉じてしまいます。ささやかな抵抗かもしれませんが、昼飲むなら前の日は早寝してみましょう。

完全に自分用防備録なのにたいそうなタイトルを付けてしまいましたが、これから飲む前にはこのエントリを読み直すことにします。

こちらもオススメ!
    None Found

PukiWikiいれてみた

4月 4th, 2008 Posted in 仕事術 | 2 Comments »

会社でwebサーバー立てたので、ついでにPukiWiki入れてみた。

いいね、これ。

今までwikiってあんまり使ったことなくて、正直便利さとかが分かってなかった。
ところが自分で設定とかページ作成とかやってみると、いろいろ面白い使い方ができるんじゃないかと思ってきた。
なんでもやってみるもんだな。

今回は開発チームのメンバー間で使うことを想定して構築したので、次のような使い方を考えてる。

  • スケジュールの共有
    Pluginでcalendar9.inc.phpというのがあって、簡単にカレンダー表示、スケジュール登録、表示ができる。
  • バグ報告
    これまたPluginでbugtrackってのがあって、簡単にバグ報告システムが使える。
  • メンバー間の連絡用掲示板
    半径3メートルいないに全員いるんだから直接話しろよってのはナシで。
  • 他部署への公開ドキュメント、便利ツール置き場
  • RSSで更新状況が分かる

便利なのはいいんだけど、問題はメンバーにWikiを使った情報共有を浸透させるのが難しいってことか。

こちらもオススメ!
    None Found

Basic認証ではまる

3月 31st, 2008 Posted in サーバー | No Comments »

恥ずかしながらApacheのBasic認証をやろうとしてはまりまくったのでエントリ。
サーバーはVineLinux4.2。
Apacheは元々入っていたヤツ。

httpd.confでBasic認証の設定をし、ページにアクセスしようとすると
認証ダイアログは表示されるけど認証に失敗する現象があった。

  1. <directory>
  2. Order Allow,Deny
  3. Allow from all
  4. AuthType Basic
  5. AuthName "test"
  6. AuthUserFile /var/www/password/.htpasswd
  7. Require valid-user
  8. </directory>

AuthUserFileには、/home/xxxなど以下のファイルを指定すると権限がないと怒られる。

怒られるのもエラーログを見ないと怒られたことに気づかない。

  1. /etc/apache2/logs/error_log

パスワードファイルをおくのは、ユーザapacheが参照できるところじゃないといけない。

こちらもオススメ!