Mercurial > hg > Papers > 2011 > koba-master
diff paper/unittest.tex @ 6:f59edc38c858
add graphic files.
author | koba <koba@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 06 Feb 2011 01:58:33 +0900 |
parents | |
children | f953f01c58bf 028ed9741872 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/paper/unittest.tex Sun Feb 06 01:58:33 2011 +0900 @@ -0,0 +1,90 @@ +\chapter{CppUnit による単体テスト} \label{chapter:unittest} +ここでは一般的なテスト駆動開発のフレームワークの例として CppUnit の紹介と、 +過去に CppUnit を用いて行われた Cerium の単体テストについて述べる。 + +\section{CppUnit} +CppUnit は、xUnit と呼ばれる、単体テストを自動化するテスティング +フレームワークの内の一つで C++ 用に開発されている。 +CppUnit の特徴はテストケースを増やすことが容易であり、1 つの事象に対して +様々なテストケースを同時にテストする事ができる。また、羅列したテストケースは +一括で実行、結果の表示ができる。(図\ref{fig:cpptest}) + +\begin{figure}[h] +\includegraphics[scale=0.6]{images/test_example.pdf} +\caption{CppUnitTest} +\label{fig:cpptest} +\end{figure} + +\newpage + +\section{CppUnit によるゲームプログラムの単体テスト} +我々は過去に CppUnit を用いてゲームプログラムの単体テストを行なっている。 +このテストでは Cerium のオブジェクト管理システムである SceneGraph +(\ref{sec:scenegraph}節) を用い、3 つの SceneGraph ノードを持つオブジェクトの +テストを行った。このオブジェクトは本体の他に左右にパーツを 1 つずつ持つ。 +本体を tree の root として左右のパーツがその子供になっている。 +(図\ref{fig:boss1}) + +\begin{figure}[htbp] +\includegraphics[scale=0.8]{images/boss1_SG.pdf} +\caption{boss1} +\label{fig:boss1} +\end{figure} + +この boss1 は右に一定速度で移動し、画面上の適当な位置に来ると State パターン +により左方向への移動に状態が遷移する、簡単なゲームの例題となっている。 + +\begin{verbatim} +static void +boss1_move_right(SceneGraphPtr node, int screen_w, int screen_h) { + node->xyz[0] += node->stack_xyz[0]; + if(node->xyz[0] > screen_w-280) { + node->set_move_collision(boss1_move_left, boss1_collision); + } +} + +static void +boss1_move_left(SceneGraphPtr node, int screen_w, int screen_h) { + node->xyz[0] -= node->stack_xyz[0]; + if(node->xyz[0] < 280) { + node->set_move_collision(boss1_move_right, boss1_collision); + } +} +\end{verbatim} + +このテストでは root のアドレスを取得し、そこから tree を辿って +各オブジェクトの座標を取得し、その初期化が正しいか、状態遷移において正しい +値を保持しているか調べた。 + +\begin{verbatim} +void +sgTest::rootTest() { + test_init(); + + sg_root->print_member(); + CPPUNIT_ASSERT_EQUAL((float)width/2, sg_root->xyz[0]); + CPPUNIT_ASSERT_EQUAL(0.0f, sg_root->xyz[1]); + CPPUNIT_ASSERT_EQUAL(-100.0f, sg_root->xyz[2]); +} + +void +sgTest::childTest() { + while (sg_root) { + if(sg_root->children != NULL) { + sg_root->children->print_member(); +... + sg_root = sg_root->children; + } else if(sg_root->brother != NULL) { + sg_root->brother->print_member(); + CPPUNIT_ASSERT_EQUAL(0.0f, sg_root->brother->xyz[0]); +... + sg_root = sg_root->brother; + } else { + ... +\end{verbatim} + +このテストの結果、全てのオブジェクトの初期位置と状態遷移した値が正しいことが +分かった。しかし、ここで行った単体テストはゲームにおける、ある一瞬の値の正誤 +しか調べることができない。ゲームプログラムは時間の経過と共にオブジェクトの +パラメータが常に変化するため、こうした一般的な単体テストではゲームのバグを +発見するのは難しい。