戻る 進む

ちゅうわけで、テストコードの実装から続き。

vim CalcTest.cpp

 1  #include "CalcTest.h"
2
3 /*
4 @TARGET
5 ../Calc.h
6 */
7
8 /*
9 @PRIVATE
10 Calc* calc;
11 */
12
13 void CalcTest::setUp () {
14 calc = new Calc;
15 }
16
17 void CalcTest::tearDown () {
18 delete calc;
19 }
20
21 //========================================
22 // Test Cases
23 //========================================
24
25 void CalcTest::test_add () {
26 CPPUNIT_ASSERT_EQUAL( 2, calc->add(1,1) );
27 CPPUNIT_ASSERT_EQUAL( 1, calc->add(1,0) );
28 CPPUNIT_ASSERT_EQUAL( 1, calc->add(0,1) );
29 CPPUNIT_ASSERT_EQUAL( 0, calc->add(0,0) );
30 CPPUNIT_ASSERT_EQUAL( 9, calc->add(6,3) );
31 CPPUNIT_ASSERT_EQUAL( 9, calc->add(3,6) );
32 }
33
34 void CalcTest::test_sub () {
35 CPPUNIT_ASSERT_EQUAL( 0, calc->sub(1,1) );
36 CPPUNIT_ASSERT_EQUAL( 1, calc->sub(1,0) );
37 CPPUNIT_ASSERT_EQUAL( -1, calc->sub(0,1) );
38 CPPUNIT_ASSERT_EQUAL( 0, calc->sub(0,0) );
39 CPPUNIT_ASSERT_EQUAL( 3, calc->sub(7,4) );
40 }
41

↑このように編集しました。
@PRIVATEのところは自作スクリプトでクラス定義をヘッダファイルに出力する時に、private変数として宣言されます。 つーかそのまま出力されます。
setUpとtearDownはテストケース(この場合はメンバ関数)の実行前と実行後に呼ばれるので、初期化処理と後始末の処理を書いておきます。

いちおうマクロももう一度書いときます。
CPPUNIT_ASSERT( condition ); conditionが偽(false,0)の時に失敗
CPPUNIT_ASSERT_MESSAGE( message, condition ); 偽の時に失敗してmessageを出力
CPPUNIT_FAIL( message ); 必ず失敗してmessageを出力
CPPUNIT_ASSERT_EQUAL( expected, actual ); 得られた結果actual!=期待する値expectedの時、失敗
CPPUNIT_ASSERT_EQUAL_MESSAGE( message, expected, actual ); CPPUNIT_ASSERT_EQUALで失敗した時message を出力
CPPUNIT_ASSERT_DOUBLES_EQUAL( expected, actual, delta ); 浮動少数値のEQUAL。誤差はdeltaで指定する。


そんではテストを実行します。
その前に、えーと、テストはnmakeして出来上がった実行ファイルを実行するだけなんですが、これを打つのもめんどくさいんで、test.batを作っ てtestと打つだけでいいようにします。

vim test.bat

1  @ECHO OFF
2 call "C:\Program Files\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT"
3 nmake -f makefile TestRunner.exe
4 TestRunner.exe

これでtestと打つだけでファイルの更新チェックとビルドとテストの実行が自動化されました。TestRunner.exeだけビルドしてますけど、別 にこれはTestRunnerGUI.exeでもいいです。大抵どっちか片方だけしか使いませんから。スクリーンショットを撮って貼るのがめんどくさいと いう理由でここではTestRunner.exeを使ってます。


ほんでは

test

makeがCalcTest.hを更新して、コンパイルとリンク処理をして、テストを実行して結果を表示すればOKです。テスト結果を見る前に CalcTest.hがどういう風に自動更新されたか確認してみます。いちいち見なくてもいいんですが一応最初は確認しながらということで・・・

vim CalcTest.h

 1  #ifndef DEFINE_UNITTESTS_H_CalcTest
2 #define DEFINE_UNITTESTS_H_CalcTest
3
4 #include <cppunit/extensions/HelperMacros.h>
5
6 #include "../Calc.h"
7
8 class CalcTest : public CppUnit::TestFixture {
9 CPPUNIT_TEST_SUITE( CalcTest );
10 CPPUNIT_TEST( test_add );
11 CPPUNIT_TEST( test_sub );
12 CPPUNIT_TEST_SUITE_END();
13
14 private:
15 Calc* calc;
16
17 public:
18 void setUp ();
19 void tearDown ();
20
21 protected:
22 void test_add ();
23 void test_sub ();
24
25 };
26
27 #endif /* DEFINE_UNITTESTS_H_CalcTest */
プライベート変数が追加されてたり削られたテストケースがあったりCalcTest.cppの変更に従って更新されているのがわかります。


じゃあテストの結果に戻って・・・

(テストの結果)

.F.F

!!!FAILURES!!!
Test Results:
Run:  2   Failures: 2   Errors: 0


1) test: CalcTest.test_add (F) line: 26 CalcTest.cpp
expected: 2
but was:  0

2) test: CalcTest.test_sub (F) line: 36 CalcTest.cpp
expected: 1
but was:  0



と、これも失敗なのを確認して一応テストケースの作成は終了です。で。やっとCalcクラスの実装にとりかかります。
確認しておきますが、今はtestsディレクトリ中にいて、Calc.cppはひとつ上の階層にあります。
では実装をば・・・(というほど大げさではないですが)

vim ../Calc.cpp

 1  #include "Calc.h"
2
3 int
4 Calc::add(int x, int y) {
5 return x+y;
6 }
7
8 int
9 Calc::sub(int x, int y) {
10 return x-y;
11 }

実装完了!(速)
では、すかさず

test

Calc.objをコンパイルしなおしてTestRunnerをビルドしなおして実行して結果が出力されます。

(実行結果)

..

OK (2 tests)


というわけで、めでたくテストも通ってCalcクラスが完成しました。



でも、機能が貧弱であまり面白くありません。なので。次に仕様追加ということで掛け算と割り算をするメンバ関数mul、divをCalcクラスに追加して みます。



つづく