本文書は、ノベルゲームを作る上で、スクリプタが実施すべきテストについて 述べる。対象は「システム」(=プログラム)であり、立ち絵とかシナリオ分岐とかの テスト方法にはあんま触っていないことに注意。
これを実施したからといって、バグがモノスゴ減って安定したゲームが ばんばん量産できるようになるわけではないけれど、これを実践しないと 間違いなくバギーでトゥーバッドでユーアーベリーノーなゲームを 量産することになっちゃう、といういつもどおりの微妙な体(てい)で。
なお、語句は一般のソフトウェアテストのそれと統一されてないことがあるのを 予め断っておく。ニュアンスが伝わればイインダヨ!
案外気にしてない人が多いので一応書いておく。というかこれ気にせずにテスト しちゃダメだと思う。
もちろん、テストにより不具合を事前に叩き出し、これを修正するのが直接的な目的。 しかし、もっと高い視点から見よう。さすれば見えてくる、主な理由は以下の二つ。
バギーなゲームを作り上げてしまったとしよう。インターネット全盛の昨今、 「XXってゲームはバグ多くってさー…」という情報は、本当にあっという間に 広まる。さすればこれを見て購入を躊躇うユーザが増加することは避けられない。 当然、売り上げが落ちる。「リリース直後に修正パッチを出したからO.K.」ではない。 世の中には、パッチの当て方が判らなかったり、 そもそもそういうもので後から品質改善ができるということすら知らない人もいる。 パッチリリースの手間とコスト、テスト工数もバカにはならない。 だから、最初からカンペキを目指さなければならないのだ。
もっと言えば、コトは更に重篤な場合だってある。酷いバグを残したまま 製品をリリースした場合、 「XXってゲームの○○ってスクリプタは大バグ残したままリリースしやがった」 という事実が残る。アナタの職業的な評判はがた落ち、下手すると死活問題に 発展しかねない。
更に更に厳しいことを言えば、周囲への悪影響だって甚大だ。バグ出した 本人だけが迷惑を被るなら自業自得だが、「△△ってメーカーのゲームは いつもバグが多い」なんてことがマコトシヤカに囁かれるようになると、 メーカー・ブランド存亡の危機にすら発展しうる。 それもこれも、全てはキミがちゃんとテストしなかったからだ! 一体どうしてくれるんだッ!
…とか言いながら、一応フォローを。我輩、 前工程(シナリオ、演出、絵、サウンドなど)が遅れに遅れた挙句、諸般の事情で 締め切りを延期することができず、 十分なテスト時間が取れなくて酷いバグが沢山残ったゲームをリリースしちゃった例を 知っている。ので、バグがあることが必ずしもスクリプタが悪いとイコールなわけでは ないことは「我輩は」理解できる。ユーザに理解してもらうのはムリだけどね。
スクリプタにできることは、不具合のないシステムを組み上げることだ。 シナリオはシナリオライタが作る。デザインはデザイナーが作る。 他の部分に残念なところがあったとしても、少なくともスクリプトが残念なことに ならないようにしよう。小指の先ほどの大きさのスクリプタプライドにかけて。
そしてもうひとつ、「全てのプログラムにはバグがある」という、 悲観的だが否定しきれない現実も忘れずに。「ま、動くだろ」と安易に考えた 時点で負けは確定する。負けるな!
何のためにテストをするのかと問われれば、不具合をなくすため、と答えるのが 世の定め。でも、じゃぁどうやってテストするのかと問われて論理的な回答が 出来る人は少ないように思う。知っとけ!テストとはロジカルに実行して初めて 意味があるものなのだよ?
というところで、以下にテストの勘所を示す。
モノを設計する時は概念から作るが、実際にモノを作る・テストする時は最も細かい 末端部品から行う。これが世界のルール。最終的なモノが「細かい部品を集積して 出来上がっている」以上、細部がカンペキでなければ全体がカンペキになることは 決してない。だから、独立してテスト可能な末端の部品から、徐々に徐々に 上位に向かってテスト範囲を広げるのが効率的なテストの鍵だ。
全体のテストはもちろん不可能だが、少なくとも 以下で述べる単体・モジュールテスト、あわよくばプログラムテストは、 スクリプタの手元で実施可能だ。その部分のコーディングが終わった、と思った その時に、すかさずちゃんと動くかどうかのテストを実施すべきだ。 後からやろうやろうと思っていると、絶対にテストしない。今だ!今しかないんだ! くらいの気持ちで、すぐにテストに臨め。
基本的に修正は悪だ。それは新たな不具合を作りこみ、それに関係する 他のモノモノに多大に影響し、時には全体を破壊することすらありえる。 だから、テストが完了し、必要十分な機能が正常に動作することが証明された部品は、 決してそれ以上修正してはならない。新たな問題が発覚し、どうしてもテストが終了 した部品を修正しなければならない場合は、修正後、修正箇所に関わるテストを 全てやり直すこと。そうでなければ、カンペキな部品とはなりえない。
これは「テスト」とは直接関係ない話だけれども一応。 修正を施す場合、その範囲は可能な限り小さく留める。影響範囲が大きいと、 他の部品にも思わぬ悪影響を与えるし、再テストの手間も指数関数的に増加する。 「綺麗に直そう」とか思うな。少々汚くても、修正内容が必要十分で、 修正箇所が最小限にとどまるのが良い修正。綺麗にしたかったら、最初から バグなしで作ればよかったのだ。それができなかった自身の無能っぷりを呪え。
いかに自動化したとしても、全ての入出力をテストすることはできない。 従って、上手に手を抜きつつ、必要十分なテストを実施することが肝要になる。 …でもまぁ、ホワイトボックステストとか正常・異常・境界ケースとか言われても ピンとこないよね普通。なので、この文書では可能な限り簡略化して その方法を述べる。
論理的、網羅的にテストするのにはもうひとつメリットがあって、それは 「自動化可能な部分を発見できる」こと。テストの自動化はテスト効率を飛躍的に 向上させる。是非考えるべきだ。論理的に項目を作れば、それができる。
「そんなの普通の人はせんでしょ」というテストもあえて実行する。 プログラム・スクリプトは論理的なものであり、なんかのタイミングで 不具合が発生する、なんてのは、即ち大バグだから、「バカなことされても ちゃんと動くこと」は実は必須要件なのだ。 後述するが、「一秒間マウス20連射ァァァァ!」のような一見アホ丸出しのテストが、 時に重篤な問題を未然に抽出してくれることだってあるのだから。
案外忘れがちなのがこれ。「あれ、これなんでだろ」と思ったものは、すべからく メモして、調査して、原因を追究しなければならない。そうでなければテストの 意味が無い。ちょっとした不具合は、後に重篤な別の不具合を引き起こす原因となる。 だから、問題は必ず、その原因を明確に突き止めて、問題あるかないかを判断 しなければならない。
問題は常に再現するとは限らない。一度再起動したら発生しなくなったからいいやー、 というアホみたいなことを防ぐために、問題が発生したら、デバッグウィンドウとかで その問題をとことんまで調査せよ。なぜ起こる?内部変数はどのようになっている? これらを、TJSソースコードと首っぴきで入念に調査せよ。ここで判らないなら、 おそらくアナタにはコレを解決する能力が無いのだ。
ちなみに、printfデバッグ(プログラム中にデバッグメッセージを出力するような
論理を追加すること)は極力避けること。TJSであれば、ちゃんとデバッガで
内部情報まで参照できるんだから、printfデバッグする意味は殆ど無い(ステップ
実行があればもっといいのにね)。また、
余計な論理を追加することでタイミング問題が発生しなくなることだってある。
そもそも、printfデバッグのためには問題が発生しているプログラムを
一度終了しなければならない。終了してはだめだ!
再現しなかったら問題の原因を探ることが永遠に不可能になってしまう!
エンタープライズ分野では、printfデバッグは素人かアホの子が
すること、と忌避されている理由を、少しは考えよう。
絶対に使うな、とまで言わない。しかし、本来そうすべきではない、ということ。
まぁつまりそのアレだ、少なくともこの文章くらいは読んで咀嚼しとけ、と。
ここからは、じゃあ実際テストする時どうやっていくべきか、を具体的に述べる。 正直、こういうテストは結構面倒だ。面倒なんだけど、それを乗り越えて実施する ことで、一つ上の品質が手に入るのだ、と思って頂ければ幸いであるよ。
テストは、「単体・モジュールテスト」、「プログラムテスト」、「トータルテスト」 の三段階に分けて行う。最初は細部から、徐々に全体をテストする、ような形であると 理解していただければ幸い。
以下は必ず最初に実行すること!これだけでずいぶん能率が上がる。是非。
まず、最小分割単位でテストを行う。KAGなら「他のマクロをを呼び出さないマクロ」、 TJS2なら「他の自作関数を呼び出さない関数」が最小分割単位だ。 他のマクロや関数と関わっているようなものは、こういうシンプルな最小部品の テストがすべて終わってからテストを開始すること。そうしないと、 直していくうちにどんどん修正箇所と再テスト箇所が増加してハマっていく。
例えば、ここでは、以下のようなTJS関数をテストすることを考える。 この関数は、「指定した画像ファイルが存在するかどうかを調査して、true/falseを 返す。ただし、画像ファイルは拡張子を指定する必要はなく(指定してもよい)、 拡張子 png/tlg/jpg/bmp については自動的に付加してチェックする」もの。 なんでこんなものが必要なのかは、この次のマクロを見れば判るから とりあえずここでは述べない。
[iscript] // 指定した画像(拡張子あってもなくてもいい)が存在するかどうか function existGraph(g) { var q = Storages.isExistentStorage; return q(g) || q(g+'.png') || q(g+'.tlg') || q(g+'.jpg') || q(g+'.bmp'); } // "abc.png" と "abc.png.tlg" が存在したら区別つかんがな、とか、 // 指定されたファイルがテキストファイルだったらどうすんの、という指摘はガン無視 [endscript] |
テストの肝は、簡単に言えばその部品中の すべてのコード、分岐が網羅的に実行されるように 入力を選んでその部品を呼び出し、出力が予想と同じかどうかを確認すること。 上のexistGraph()関数なら、拡張子なし・拡張子あり(.png、.tlg、 .jpg、.bmp)それぞれについて、ファイルが存在する・しない場合に、正しく 結果が返ってくるかをチェックすることになる。
テスト前に、簡単でいいので、なにをテストし、どういう結果が期待されているか、 という表を書いて欲しい。
呼び出し方 | ファイル有無 | 予想される返り値 |
---|---|---|
existGraph("abc") | 画像ファイル"abc*"が存在しない | false |
existGraph("abc") | 画像ファイル"abc"が存在する | true |
existGraph("abc") | 画像ファイル"abc.png"が存在する | true |
existGraph("abc") | 画像ファイル"abc.tlg"が存在する | true |
existGraph("abc") | 画像ファイル"abc.jpg"が存在する | true |
existGraph("abc") | 画像ファイル"abc.bmp"が存在する | true |
で、あとは 画像ファイルの有無をこの表に従って変更しながら、TJS レベルで existGraph("abc") を呼び出しまくる。計6回。そのくらいはさくさくやろう。 これで、existGraph()が意図したとおりに動くかどうか、全ての分岐を舐めて 確認できたはずだ。
それが終わったら、次にこの関数を利用する関数・マクロををテストする。 ここでは、KAGマクロ[image_load]を対象としよう。このマクロは、 「画像ファイルが存在していたら指定されたレイヤに読み込み、そうでなければ 白画面に画像ファイル名を表示」する。ゲーム作り始めのころ、素材が揃わない 時にもエラーなく実行できて便利。
; 指定された画像を指定されたレイヤに読み込む。ファイルが無い場合は白地に ; ファイル名文字列を表示する ; [image_load layer=0(def) page=fore(def) left=0(def) top=0(def) storage=] [macro name="image_load"] ; デフォルト値設定 [eval exp="mp.layer = 0" cond="mp.layer === void"] [eval exp="mp.page = 'fore'" cond="mp.page === void"] [eval exp="mp.left = 0" cond="mp.left === void"] [eval exp="mp.top = 0" cond="mp.top === void"] [layopt *] [if exp="existGraph(mp.storage)"] ; ファイルが存在した場合 [image *] [else] ; ファイルが存在しなかった場合 ; トータルテストの際は、ここを以下一行に変更することを勧める ; [eval exp="System.inform('エラー、画像ファイルがありません: ' + mp.storage)"] [image * storage="white"] [ptext * text=%storage x=32 y=32 size=32] [endif] [endmacro] |
さて、上のマクロをテストするにはどうしたらいいだろう。「全部舐める」ように 入力を決め、想定した出力になるかどうかを確認すればいいのだから、 そういう形で入出力を決めるべき。ここでは、existGraph()関数は 「カンペキに動くはず」と考えてよい。上で既にテスト済みだからこそできる判断。
呼び出し方 | ファイル有無 | 予想される動作 |
---|---|---|
[image_load storage=abc layer=0 page=fore] | 画像ファイル"abc.*"が存在しない | layer=0 page=foreに白地に"abc"が表示される |
[image_load storage=abc] | 画像ファイル"abc.png"が存在する | layer=0 page=fore "abc.png"が表示される |
[image_load storage=abc layer=1 top=100 left=100] | 画像ファイル"abc.png"が存在する | layer=1 page=fore top=100 left=100 に"abc.png"が表示される |
このくらいのマクロにバグが入るわけないじゃん、という方が居るかもしれない。 そういう方のために、上のマクロにはあえてバグを残しておいた。 二番目のテストでエラーになる。しかし、結構深いお話なので、 コード見て判る人は多分居ないだろう。試して、エラーメッセージ読んで、 エラーの意味をかなり考えて、それで初めてバグの存在が判るようになるはずだ。 テストの重要性を身をもって知るがよいわ!
以上を繰り返すことで、関数・マクロの小部品が、意図した通りに動作することが 確定する。確定させないままこの先に進んではいけないよ?
ある程度モジュールテストが終わると、それらを組み合わせて大きな機能単位ごとの テストができるようになる。これをプログラムテストという。ゲームで言えば、 例えば CGモード、タイトル画面、スタッフロール、ロード・セーブ画面など、 単体でほぼ完結する機能ごとにテストを実施する。これらのテストも、基本的には 単体・モジュールテストと同じ、「全パスチェックし、入力・出力が正しいか 確認する」のがテストスタンスだ。ただ、ここまで大きくなってくると、それぞれに 全く異なるテストマトリックスが必要になる。ここでは共通したテスト項目を 書いておこう。エラーが起こりやすい例を織り交ぜてある。
メモリリークを探すのはかなり難しい。吉里吉里は画像を読み込む時にそれを キャッシュするので、見かけ上のメモリ使用量は増加しがちだからだ。 デバッグウィンドウで「System.doCompact()」を実行すると不要なメモリを 開放してくれるので、適宜これを実行してメモリ量が増加していないか確認すると よい。…これでも正確じゃないんだけど。一応、吉里吉里の コマンドラインオプションに --memusage=low とか -gclim=0 とか指定するとメモリ使わないようにはなるが、 これらもカンペキじゃないんだよね…目に見えて遅くなっちゃうし。
表示レイヤー数が増加しているかどうかは必ずチェックすべきだ。システムボタンを 表示してるゲームではありがちなんだが、よーく調べてみると「以前のシステム ボタンを消去せずに次のシステムボタンを表示してた」なんてことがあって、 (同じ場所に重ねて表示されるので)見かけ上は全く変わらないのに、 調べてみるとトランジションのたびにボタン数が増えていた、なんてことが よくある。こういうのは、一つチェックスクリプトを書いておくことをお勧めする。 我輩は拙作TJSFunctions の中に、printLayers() という関数を用意した。これを使えば、現在 layerがどのように表示されているかがパツイチでわかる。今週のオススメ。
ゲームスクリプトが全て完成し、分割して作っていたモジュール・プログラムを全て テストし終わったら、全てを組み合わせて、いよいよ最終テストに入る。 残ったバグはここで全て叩き出すことを念頭におきつつ、代表的なテスト方法を 以下に列挙する。
autoでゲームクリアできるか、skipでゲームクリアできるか、は、ゲーム中に ゲームを停止させるような不具合がないことを確認するために実施する。あと、 autoが快適か、skipが快適か、どこか遅いところはないか、を確認することも 兼ねている。当然、立ち絵や背景の指定抜け、画像不一致などもあわせて チェックする。これはもう必須テストと言っても過言ではない。
「高速自動マウスクリックツール」は我輩のオススメ。スクリプトが大きくなれば なるほど、タイミングの問題で不具合が発生する可能性が高くなる。 短期間での多重クリックは、裏ではスキップを呼び、ロックや排他処理が原因で 発生する不具合を叩き出す有効なツールとなる。我輩も、「ユーザ先では 時々起こるけど、自分のところではどうしても再現できなかった問題」を こういうツールを使って再現させたことが何度かある。そんなに時間は かからない(そもそも高速スキップされちゃうから)ので、是非一度試して 頂きたい。 我輩はFortuna を使わせてもらっている。Home/EndでOn/Offが切り替えられるのがとても便利。
「再起動なくゲームを複数回クリアする」ことの目的は、メモリリークの発見。 クリアし終えたら、Windowsのタスクマネージャを起動して、krkr.eXe(または アナタのゲームのexe名)のメモリ使用量をチェックする(System.doComact()を 忘れずに)。どのくらいになるかは ケースバイケースだが、起動直後、1ループ目、2ループ目と比較して、 明らかにメモリ使用量が増加しているようなら、 どこかにメモリリークがあるかもしれない、と疑うべきだ。 通常は多くてもゲーム全体で500MBを超えるメモリが消費されることはない。 起動時と今との差分が1GBを超えるようなら、よっぽど凝ったゲームで無い限り それはメモリリークを含んでいる可能性が極めて高い。死ぬ気で原因を探ること。 タスクマネージャとにらめっこしながら、「何をしたらメモリ使用量が劇的に 増加するか」をチェックし、そのキッカケを発見したら、次はその動作を 細分化し、どこが原因かを探っていく。最終的には全マクロの一行ごとに[l]を 入れていくくらいの地道な作業だが、絶対に必要な作業だ。
同時に、プレーし続けていくと徐々に操作感が悪く(反応が鈍く、重く) なっていかないかもチェックする。メモリリークなどが無い限りはそうでもないが、 前述のようにレイヤの消去忘れがあったりすると、扱うレイヤ数が増加し、 だんだん重くなることは十分ありうる。
以上のような、とにかく色々やってみて、何度もループ回してみて、それで 問題が起こるかどうか、というのを探すのがこのテストの目的だ。ユーザは びっくりするような操作をする。それを読み、予め対応しておくのが カッコいいスクリプタ。
ゲームを最初から最後まで全部流して人力チェック、だと、間違いなく チェック漏れが発生するから、こういう機械的にできることは、全て 機械的に実施することが成功の鍵だ。 アナタがプログラマを自称するなら、以下のようなスクリプトをperlなどを利用して 予め作っておくべきだろう。
チェックしたら、当然「どのスクリプト(シナリオテキスト)ファイルの、 何行目の、どういう指定が、どういう理由でエラーであり、どう直すべきか」を CSVファイルか何かで吐き出し、表に纏めて くれるようなツールだとよい。この手のツールは一日あれば作れるものだ。
まぁそのアレだ、こういうスクリプトは、最初はシナリオテキスト→シナリオ スクリプトの段階で流すべき。で、元のシナリオテキストをどんどん修正していって、 エラーが無くなってからシナリオスクリプトを確定すべきだと思うな。 実際にはシナリオスクリプトにも修正が入るから、トータルテストの前に 再度チェックすることが必要なんだけれども。
これが最も難しい。ゲーム中のルートテストは、要するにシナリオ上の分岐を 全部舐める形で実施しなければならないが、スキップ機能が貧弱だととんでもない 時間がかかる。 だもんで、そこはスクリプタの腕の見せ所、スキップを高速化したり、 選択肢やフラグ間の処理を全てスキップできるように シナリオスクリプトを組み上げる。さすれば、ルートテストは飛躍的に楽になり、 「あのゲーム、スキップが超優秀」と世間の 評判もうなぎのぼり、鼻高々でムッシュムラムラ(?)、仕事はどんどん舞い込み 一年後には億万長者となること相違なし!(夢見がち)。
…なんか他に有効でトレビヤンな方法ってないかしら。絶賛募集中。ナイスアイディア をくれた人には…飴ちゃん一つあげちゃうよ?
そんなイカす方法があるのか?と問われれば、ある、と答えよう。実際、ある。 もちろんプリントアウトされたプログラムリストは必要だが、最初のデバッグには PCは無くてよい。その方法の名は「デバッグ猫」。簡単に言えば、 「誰かにプログラムを一行一行説明する」作業。この「誰か」は実は誰でもよく、 我輩の経験では実際猫のヌイグルミに向かって喋ってる人を見たことがあり、 だからこの名が付いた。
この方法の効果は案外バカにはならない。人(?)に説明するということは、 コードを理解し、整理し、動作を想像しながら発言するということだ。 だもんで、発言者は説明中に「あれ…そういやX○ってケース考えてないな…」 などともりもり気付く。 本当にびっくりするくらい気付く。疑ってる人はぜひとも実践してみて欲しい。 ある程度発声する必要があり(頭の中で発音してはダメなのだ)、 電車の中で実施するにはちょっと勇気が要るのが難点。 でも、旅先の恥は掻き捨てよってばっちゃかゆってたし。うん。
ヘンだな、と思ったことはとことんまで理由を明確にせよ。そこにバグが潜んでいる。 そこを修正するかどうかは、原因を明確に突き止めた後判断すべき。原因のわからぬ ちょっとした違和感は、後に巨大な不具合を引き起こす原因になる。 「立ち絵表示が遅いなぁ」というのだって、 もしかしたらモノスゴ無駄な処理をアナタが作りこんでしまっている結果かも しれない。そんなことは絶対にない!と言い切れない以上、ちゃんと原因追求すべき。 これを怠る人はプログラマ・スクリプタには向かない。
遅いな、と思ったら、すかさずSystem.getTickCount()で時間を計り、実際どのくらい 遅いのかを定量的に把握せよ。 どこがどの程度遅いかはっきり分かれば、それが適当かどうか、回避可能かどうかが 判断できるようになる。ケースバイケースなので明確には言えないが、 少なくともどこが遅いかを把握することは、問題を抽出する第一歩にはなる。
TJS周りでエラーが出た時、デバッグコンソールにはトレース情報が表示される。
読み方はこちらで解説済み。これくらいは
読んでおこう。
あとマメ知識。その関数がどこから呼び出されたんかいな、というのは、TJSであれば
Scripts.getTraceString()
でバッチリ判る。呼び出し経路が必要なら、これを使うのも覚えておこう。
吉里吉里が止まってしまい、入力を受付けなくなることが時々ある。なにやっても ダメ、CPUリソースは100%食ってるし、なんかメニューが白くなって何も押せない、 なんてことになったら、これは間違いなくどこかでTJSの無限ループにハマっている。
しかし、吉里吉里で無限ループに陥った時にその箇所を探しだすのは極めて難しい。 吉里吉里は無限ループを停止させる術を持たないからだ。試しに、 以下のようなfirst.ksを実行してみるといい。右上のXボタンを押すか、 タスクマネージャで強制停止するか以外何もできないことがわかるだろう。
[iscript] while (1); [endscript] |
ではどうするか。まずは現象が発生した箇所を特定することだ。実際にはゲームを 流している最中に起こるだろうから、その時に「どの箇所で」現象が出たかを 記録する。「シナリオXXの1000行目くらい、A子がXXするところ」くらいまで わかればいい。あとは力技、その近辺だけを抜き出して繰り返し実行する スクリプトを作り、現象を再現させる。再現したら、更に「どこで」発生 しているかを絞り込む。一部の処理をコメントアウトして問題が起こらなくなったら、 「コメントアウトした部分に問題がある」ことがわかるし、コメントアウトしても 問題が起こるなら「コメントアウトしなかった部分に問題がある」ことがわかる。 これを二分木法で検索すれば、少々時間はかかっても、根っこが見えてくるはずだ。
誰かデバッガ作ってくんないか。無限ループが「どこで回っているか」を教えて くれるだけでいいからさ。
テスト中は、first.ksの最初の最初で、patchtestディレクトリをStorageパスに 追加しておくことをお勧めする。これにより、data/patchtest ディレクトリに 入れたファイルが、他の全てのファイルをOverrideするようになる。
; パッチテスト用フォルダを追加。製品版ではコメントアウトすること [eval exp="Storages.addAutoPath('patchtest/')"] |
ゲームリリース後にパッチを作成する際など、 このディレクトリにパッチ済みファイルを放り込むことで、 他のファイルを一切変更することなくパッチテストが存分にできるというメリットが ある。もちろん、ゲームリリース前でもこの仕組みは使える。 「元ファイルを変更することなく、あるファイルを変更した動作を確認することが できる」というのは、マスターアップ直前で、変更の影響を可能な限り避けたい 場合にもかなり重宝するだろう。
もちろん、テストが終わった後(リリース時)にはこの行はコメントアウトし、 data/patchtest ディレクトリは空にしておかねばならない。 割れ厨関係者にアタックのキッカケを残すことになりかねないし、 うっかりファイルが残っていると、 二度とそのファイルを上書きできなくなってしまう。
…とまぁ、ちょっとしたリスクはあるが、注意すれば回避できるし、 そのメリットは絶大だ。
ゲームのテストはさまざまな人が実施するし、確認のために「途中からテストしたい」 なんてことは頻繁に起こる。だから、少なくともシナリオファイルごと、できれば 更に細かい章ごとにテストプレイができるような、テスト箇所リンク一覧画面を作って おくことをお勧めする。たったこれだけで、テスト効率が飛躍的に向上するはずだ。
致命的なエラーが発生した時、それをどう扱うか、は大きな課題だ。 我輩は、ユーザの利便を第一に考え、通常は以下のように定義している。
最初は素材が揃わないから、プログラムテストまでは、素材不足によるエラーは 表示しないほうが楽だ。反対に、スクリプトエラーはどんどん表示して デバッグ対象にしなければならない。
トータルテストでは素材は全て揃っているはず(反対に、この時点で揃ってないと デスマーチ確定なので脱兎することをお勧めする)なので、この時は素材不足は 即エラーとし、素材不足を許さないようにする。これで、画面真っ黒や のっぺらぼうの立ち絵表示などの問題を防ぐことができる。
そしてリリース版。 ユーザはバグを望んでいない。問題が発生した時、そこでゲームが中断されて どうやっても先に進めないよりは、少々画面が崩れても先に進めた方がいい。 だから、必要十分な情報はログに残しつつ、リリース版では可能な限り ゲームを継続させるのが正しい(と思う)。
つまり表にするとこんな。わざわざ表にしなくていいか。
状況 | スクリプトエラーの対応方針 | 素材無エラーの対応方針 |
---|---|---|
単体・モジュールテスト中 | 検出・表示しゲームを止める | 検出・表示せずゲームも止めない |
プログラムテスト中 | 検出・表示しゲームを止める | 検出・表示せずゲームも止めない |
トータルテスト中 | 検出・表示しゲームを止める | 検出・表示しゲームを止める |
リリース版 | 検出するが表示せずゲームを止めない | 検出するが表示せずゲームを止めない |
甘いソフトハウスだったり、締め切りが近づいたりすると、真っ先に削られて しまうのがテスト時間。なぜだ!不具合を修正するための最後の砦だというのに! 感覚では、テキスト1MBあたり、最低でも一週間、できれば二週間はテスト期間は 必要だと思う。そうでないと、十分に不具合を抽出できない。是非テスト期間を 削らないで頂きたい。お願い、ディレクターの中の人。
如何だったろうか。なんてめんどくさいと思ったろうか。その通りだが、 アナタはそういう世界に肩までどっぷりであることを知るべきだ。是非面倒っぷりに 負けずにまじめにテストし、不具合をどんどん退治して欲しい。それが須らく アナタの評価に繋がる(…はず…だと思う…気がする…かもしれない)。
こういうテストの概念は全てのソフトウェアに共通する。だから、本当は、 ソフトウェア工学の「テスト」部分の工学書を是非読んで欲しい。 ホワイトボックステスト・ブラックボックステストなど、なんや難しげな 用語は一杯出てくるけれども、プログラマを自称するならそのコンセプトは 掴んでおくべきだ。…ああ、 Wikipediaのソフトウェアテスト項が結構端的に書いてあっていいかもしれんね。
ちなみに、業務用のプログラムを書いたことがある人は知ってると思うが、 いわゆる世のソフトウェアエンジニアが実施するテストは、 基本は同じなれど、上で紹介したものより はるかに複雑で精緻だ。「プログラムソースコード一行ごとに10テスト必要」と 呼ばれる程にテスト項目は多く、ちょっと大きいプログラムだと電話帳何冊分もの テストマトリックスが作成される。そこまでテストしてるのに製品にはバグが残る、 ということは、つまりそれだけソフトウェアにはバグが入り込みやすいということだ。 スクリプタもこれを肝に銘じ、テストの重要さをゆめゆめ忘るることなかれ。