annotate paper/unittest.tex @ 14:19be75493fbb

fix.
author koba <koba@cr.ie.u-ryukyu.ac.jp>
date Tue, 15 Feb 2011 18:04:22 +0900
parents d711f469cdb7
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 \chapter{CppUnit による単体テスト} \label{chapter:unittest}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2 ここでは一般的なテスト駆動開発のフレームワークの例として CppUnit の紹介と、
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 過去に CppUnit を用いて行われた Cerium の単体テストについて述べる。
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 \section{CppUnit}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 CppUnit は、xUnit と呼ばれる、単体テストを自動化するテスティング
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 フレームワークの内の一つで C++ 用に開発されている。
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 CppUnit の特徴はテストケースを増やすことが容易であり、1 つの事象に対して
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 様々なテストケースを同時にテストする事ができる。また、羅列したテストケースは
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10 一括で実行、結果の表示ができる。(図\ref{fig:cpptest})
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 \begin{figure}[h]
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 \includegraphics[scale=0.6]{images/test_example.pdf}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 \caption{CppUnitTest}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15 \label{fig:cpptest}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 \end{figure}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 \newpage
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 \section{CppUnit によるゲームプログラムの単体テスト}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 我々は過去に CppUnit を用いてゲームプログラムの単体テストを行なっている。
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 このテストでは Cerium のオブジェクト管理システムである SceneGraph
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 (\ref{sec:scenegraph}節) を用い、3 つの SceneGraph ノードを持つオブジェクトの
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 テストを行った。このオブジェクトは本体の他に左右にパーツを 1 つずつ持つ。
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 本体を tree の root として左右のパーツがその子供になっている。
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 (図\ref{fig:boss1})
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
27
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
28 \begin{figure}[htbp]
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 \includegraphics[scale=0.8]{images/boss1_SG.pdf}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 \caption{boss1}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
31 \label{fig:boss1}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 \end{figure}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
33
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 この boss1 は右に一定速度で移動し、画面上の適当な位置に来ると State パターン
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
35 により左方向への移動に状態が遷移する、簡単なゲームの例題となっている。
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
36
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
37 \begin{verbatim}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
38 static void
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 boss1_move_right(SceneGraphPtr node, int screen_w, int screen_h) {
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
40 node->xyz[0] += node->stack_xyz[0];
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 if(node->xyz[0] > screen_w-280) {
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 node->set_move_collision(boss1_move_left, boss1_collision);
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 }
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 }
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
45
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
46 static void
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
47 boss1_move_left(SceneGraphPtr node, int screen_w, int screen_h) {
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
48 node->xyz[0] -= node->stack_xyz[0];
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 if(node->xyz[0] < 280) {
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 node->set_move_collision(boss1_move_right, boss1_collision);
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 }
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
52 }
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 \end{verbatim}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
54
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 このテストでは root のアドレスを取得し、そこから tree を辿って
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 各オブジェクトの座標を取得し、その初期化が正しいか、状態遷移において正しい
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 値を保持しているか調べた。
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
58
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 \begin{verbatim}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 void
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 sgTest::rootTest() {
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
62 test_init();
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
64 sg_root->print_member();
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
65 CPPUNIT_ASSERT_EQUAL((float)width/2, sg_root->xyz[0]);
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
66 CPPUNIT_ASSERT_EQUAL(0.0f, sg_root->xyz[1]);
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 CPPUNIT_ASSERT_EQUAL(-100.0f, sg_root->xyz[2]);
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
68 }
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
70 void
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
71 sgTest::childTest() {
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
72 while (sg_root) {
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 if(sg_root->children != NULL) {
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
74 sg_root->children->print_member();
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
75 ...
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 sg_root = sg_root->children;
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
77 } else if(sg_root->brother != NULL) {
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
78 sg_root->brother->print_member();
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
79 CPPUNIT_ASSERT_EQUAL(0.0f, sg_root->brother->xyz[0]);
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
80 ...
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
81 sg_root = sg_root->brother;
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 } else {
14
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
83 ...
6
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
84 \end{verbatim}
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
85
f59edc38c858 add graphic files.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
86 このテストの結果、全てのオブジェクトの初期位置と状態遷移した値が正しいことが
9
028ed9741872 finish chapter 8.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
87 分かった。少なくとも初期化の段階でバグが発生していないことだけは保証された。
028ed9741872 finish chapter 8.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
88
028ed9741872 finish chapter 8.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
89 \section{ゲームプログラムに対する単体テストの欠点}
028ed9741872 finish chapter 8.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
90 しかし、ここで行った単体テストは、ゲームにおける、ある一瞬の値が正しいか
028ed9741872 finish chapter 8.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
91 どうかを調べるには効果的だが、常にオブジェクトのパラメータが時間の経過と
028ed9741872 finish chapter 8.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
92 共に変化するゲームプログラムにおいては有効的とは言えない。
028ed9741872 finish chapter 8.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
93 ゲームプログラムにおけるバグは他のオブジェクトのパラメータとの関係に依る
028ed9741872 finish chapter 8.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
94 ところが多く、こうした一般的な単体テストではゲームのバグを発見するのは
028ed9741872 finish chapter 8.
koba <koba@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
95 難しい。