DATE : 2006/11/04 (Sat)
(Brew Test Unit 1.0.4 対象)
想定した浮動小数点数が得られたかどうかを確認するマクロ関数に、ASSERT_EQUALS_DELTA というものがあります。(参照:テストケースの基本)
このマクロ関数では、想定値と実際の値、誤差を指定できます。
一見すると、実際の値と想定値との差が誤差の範囲内に収まっているか否かを判定するマクロ関数のように思えます。
しかし、Brew Test Unit 1.0.4 では、誤差に等しいか否かの判定になっています。
以下に示すのは、その判定部分(UnitAssert.cpp, 110~118、インデントはレイアウトにあわせて変更)のコードです。
「aExpected」は想定値、「aActual」が実際の値、「aDelta」が誤差を表します。
bool Assert::assertEquals(String aMessage, double aExpected, double aActual, double aDelta, String aFile, int aLine) { // Do comparison. if((aExpected <= aActual && aActual - aExpected == aDelta) || (aExpected > aActual && aExpected - aActual == aDelta)) { // Return True if equal. return true; }
誤差を判断している部分が、「==」となっています。そのため、この部分では、実際の値と想定値との差が誤差と等しいか否かを判断していると分かります。
参考として、JUnit で同じ機能を持つメソッド org.junit.Assert#assertEquals(String, double, double, double) のコードを挙げておきます。(Assert.java, 159~164、インデントはレイアウトに合わせて変更)
「expected」が想定値、「actual」が実際の値、「delta」が誤差を表します。
static public void assertEquals(String message, double expected, double actual, double delta) { if (Double.compare(expected, actual) == 0) return; if (!(Math.abs(expected - actual) <= delta)) failNotEquals(message, new Double(expected), new Double(actual)); }
こちらは、想定値と実際の値との差が誤差以内に収まるかどうかを判断していることが分かります。
なお、Brew Test Unit の ASSERT_EQUALS_DELTA も 誤差の範囲内に収まるような判断に変更する場合は、以下のようにコードを書き換えます。
if((aExpected <= aActual && aActual - aExpected <= aDelta) || (aExpected > aActual && aExpected - aActual <= aDelta)) { // Return True if equal. return true; }
気付くまで相当苦しめられました……orz
DATE : 2006/11/03 (Fri)
(前回の記事)
テスト用アプリケーションの記述
ユニットテストを実行するアプリケーションを記述します。
テスト用のアプリケーションは、Brew Unit Test に付属するサンプルコードを流用すると、簡単に記述できます。
サンプルコードは、「src\platforms\brew」にある brewunit.cpp です。
以下に、 brewunit.cpp の一部を転載します。(インデントなどは、記事に合わせて変更してあります)
#include "stdafx.h" // include base files for BrewTestUnit library #include "UnitTestCase.h" #include "UnitTestResult.h" #include "UnitTestSuite.h" // add brew-specific listeners support #include "stdlistener.h" #include "filelistener.h" #include "cppunit.bid" // applet class ID // add multiplatform examples #include "../examples/testcase1.h" #include "../examples/testcase2.h" static bool CppUnit_HandleEvent(IApplet * pi, AEEEvent eCode, uint16 wParam, uint32 dwParam); int AEEClsCreateInstance(AEECLSID ClsId,IShell * pIShell, IModule * po,void ** ppObj) { *ppObj = NULL; if(ClsId == AEECLSID_CPPUNIT) { if(AEEApplet_New(sizeof(AEEApplet), ClsId, pIShell, po,(IApplet**)ppObj, (AEEHANDLER)CppUnit_HandleEvent,NULL) == TRUE) { return AEE_SUCCESS; } } return EFAILED; } static bool CppUnit_HandleEvent(IApplet * pi, AEEEvent eCode, uint16 wParam, uint32 dwParam) { AEEApplet * pMe = (AEEApplet*)pi; switch (eCode) { case EVT_APP_START: AECHAR * forDraw; { CppUnit::TestResult tr; // accumulate test's statistics // create and register some listeners StandardListener stdListener; FileListener fileListener; tr.addListener(stdListener); tr.addListener(fileListener); // create main test suite with some test cases // (or test suites) and run its MyTestCase1 tc1(_T("check account")); MyTestCase2 tc2(_T("security test")); CppUnit::TestSuite ts; ts.addTestCase(tc1); ts.addTestCase(tc2); ts.run(tr); // we can use TestResult in direct way // (instead of use listeners) if (tr.failureCount() == 0) forDraw = L"Tests OK"; else forDraw = L"Tests FAILED"; } // Display result string on screen IDISPLAY_DrawText(pMe->m_pIDisplay, AEE_FONT_BOLD, forDraw, -1, 0, 0, 0, IDF_ALIGN_CENTER | IDF_ALIGN_MIDDLE); IDISPLAY_Update (pMe->m_pIDisplay); return true; case EVT_APP_STOP: return true; default: break; } return false; }
まず次の部分をテスト用アプリケーションのために生成した bid ファイルに変更します。
#include "cppunit.bid" // applet class ID
続いて以下の部分を、作成したテストケースのヘッダファイルを取り込むように変更します。
// add multiplatform examples #include "../examples/testcase1.h" #include "../examples/testcase2.h"
最後に、テストケースを生成してテストスイートに登録します。変更する部分は、次の通りです。
// create main test suite with some test cases // (or test suites) and run its MyTestCase1 tc1(_T("check account")); MyTestCase2 tc2(_T("security test")); CppUnit::TestSuite ts; ts.addTestCase(tc1); ts.addTestCase(tc2); ts.run(tr);
例えば、「SampleTest」(SampleTest.h)というテストケースを登録する場合は、次のようになります。
#include "SampleTest.h"
// create main test suite with some test cases // (or test suites) and run its SampleTest sampleTest; CppUnit::TestSuite ts; ts.addTestCase(sampleTest); ts.run(tr);
テストケースの分だけ、テストケースの取り込み、テストケースの生成、テストスイートに登録という作業を繰り返すことになります。
以上で、ユニットテストを実行するアプリケーションができました。あとは、このアプリケーションをビルドして BREW シミュレータで実行するだけです。
なお、シミュレータの「BREW 出力ウィンドウ」とファイルにテストの結果が出力されます。
(了)
DATE : 2006/11/01 (Wed)
(前回の記事)
ユニットテストの手順
Brew Test Unit を用いたユニットテストは、次のように行います。
- テスト用アプリケーションの MIF ファイルの作成
- テストケースの記述
- テスト用アプリケーションの記述
- テストスイートの記述
- テスト用アプリケーションのビルド
- BREW シミュレータで実行
- テスト用アプリケーションの MIF ファイルの作成
- BREW アプリケーションの情報を表す MIF ファイルをテスト用アプリケーション用に作ります。テスト結果をファイルに出力する場合は、ファイル特権を与えておく必要があります(ファイル特権がない場合、テスト結果はファイルに出力されません)。
- テストケースの記述
- ユニットテストを表すテストケースを記述します。詳しくは、「テストケースの基本」を参照してください。
- テスト用アプリケーションの記述
- テスト用アプリケーションを実行する BREW アプリケーションを作成します。ただし、Brew Test Unit に付属するサンプルコードを流用することができます。この部分は、後の記事で詳しく取り上げます。
- テストスイートの記述
- 実行するテストケースを Brew Test Unit に登録します。この部分も、後の記事で取り上げます。
- テスト用アプリケーションのビルド
- この部分は通常の BREW アプリケーションと同様なので省略します。
- BREW シミュレータで実行
- テスト用アプリケーションを、BREW シミュレータで実行します。テストが成功したかどうかが画面に表示され、詳しい結果がデバッグ情報やファイルに出力されます。ファイルは、テスト用アプリケーションの DLL を配置した場所と同じフォルダに出力されます。
参考文献
(つづきます)
DATE : 2006/10/31 (Tue)
風邪をこじらせた時期があったせいか、物事がいろいろと停滞気味になってしまいました。
(;^ω^)ぽっかりと記事の書かれていない時期があるのは、風邪で寝込んでいたせいです
(;´∀`)来月はちょっと頑張らないといけないかもしれませんね
(;^ω^)そういえば、先月のまとめは書いていないことに今気付きました……