【CEDEC 2019】プランナー主体のテスト駆動開発で実現したQAコスト削減と堅牢性強化…『シャドウバース』流の開発手法に迫る


9月4日~6日にかけて、パシフィコ横浜で行われたCEDEC 2019。その2日目のセッションの中から、「Shadowverse流開発手法 ~QAコスト削減と堅牢性強化を実現するプランナーによるテスト駆動開発~」の模様をお届けする。

Cygamesの技術本部クライアントサイド エンジニアである柴田有輝氏、鄒一舟氏が登壇した本講演では、『Shadowverse』(以下、シャドウバース)の開発事例を通じ、デジタルカードゲームにおけるQAコストの大幅削減を可能とするプランナー主体によるテスト駆動開発の手法が紹介された。



「『シャドウバース』では、3ヵ月に一度、約110枚前後のカード追加を伴うメジャーアップデートと、その約2ヶ月後に20枚前後の追加カードをリリースしています」と柴田氏は、現在、『シャドウバース』のカード総枚数が約2000枚、そしてスキルの組み合わせは約1000万通りほど存在していることを明かした。

このように『シャドウバース』は膨大なカードの枚数が存在。カードプール増加にともなうスキル組み合わせ数の肥大化と、それに伴うスキルロジックの複雑化により、バグの再発、チェック漏れが多発し堅牢性の低下が見られるようになったという。また、バグチェック時の再現手段も複雑化し、テストとデバック工数が増加した。

QAコストの削減と堅牢性の強化、それが課題になっているという。


▲こちらは直近1年間のカードスキルの組み合わせ数のグラフ。カードパック更新ごとに増加していることがわかる。

これらの課題に対し、"エンジニアが機能実装した時に既存機能を破壊しない"、"手戻りが発生しないことの保証"、"組み合わせに対する網羅的なデバッグ"が必要であると考えた柴田氏は、「これらを踏まえた時、我々はテスト駆動開発を提案した」という。

しかし、テスト駆動開発の導入には問題もあったそうだ。

まずAI開発において、『シャドウバース』の特性により挙動の不確定性が非常に高く、機能の正確性と有効性を両方担保できるテストシナリオが作れない。

またスキル開発面では、スキルの組み合わせ数が膨大で、シンプルなテストシナリオでは堅牢性を担保するには不十分でQAコストが右肩上がりに増えていく。

それぞれの問題点に対し、「AI側は不確定な要件の細分化でAIの良し悪しの判断をシンプルにしてテストシナリオを作りやすくする。スキル側では回帰テストと網羅的自動デバックを併用することで膨大なスキル組み合わせの堅牢性の担保とQAコストの削減を行った」と柴田氏。

そして両方の問題点の解決のため、ツール開発コストと学習コストの観点から、ツール開発時にゲームの既存機能を流用することが求められたそうだ。

では、実際にどう解決したのか? その解決策について、AI、スキルに分けて紹介された。

AI開発におけるテスト駆動開発については、AIの設計と実装を担当している鄒氏が説明。テスト駆動開発導入のための必要条件について話を始めた鄒氏は、まずAIにおけるテスト駆動手法を取り入れた開発フローを紹介した。



次にAI開発におけるテスト駆動開発の導入にあたっての要件だが、最大の問題点である挙動の不確定性から分析していったという。

『シャドウバース』は対戦相手のデッキやカードドロー、ランダム性の高いスキルなど、対戦の流れに影響しうるランダム要素が数多く存在し、「それによって、そもそも実戦で何が起きるか想像することが難しく、AIの挙動を定義するのも難しく、そうなってしまうと問題が2点出てくる」と鄒氏。

1つは、AIのプレイング優劣を判断するにはどうしても人間が必要となり、つまり自動的にテストを実行することが難しいという問題。

そしてもう一つが、開発中によく起こるプランナーからエンジニアへの手戻り案件。それを分析してみたところ、結果的にエンジニアの実装が原因で戻ってきたケースが20%未満だったのに対し、プランナーがテストプレイした際に機能は仕様通り動いたがやはり使えなかったというケースが8割以上だったという。



「どうしてそうなったのか? それはAIの不確定性により、とるべき行動を定義しづらく、正確な仕様が作りづらい。つまり、仕様そのものが信用できないという深刻な問題が発生した」と鄒氏は語った。

2つの問題点をまとめると、実装の効果検証には人間の判断が必要で自動テストの実行が難しい。そしてAIの正解が定義しづらく仕様そのものの信頼が低下するという。

これを受けて、テスト駆動開発を導入するために必要な条件として「機能要件の有効性を保証することと、挙動の正確性を機械的に判断できるようにすることを実現しなければならなかった」(鄒)

その解決策として、テスト駆動開発の主導権をプランナーに渡した。鄒氏は、「プレイングの優劣を判断する人も
仕様を作る人もプランナー。問題の原因を作った人こそが、問題の解決に最も適任」という。つまり、プランナーに協力してもらうことが一番手っ取り早く問題を解決できると考えたわけだ。

『シャドウバース』開発チームには、TCGプランナーという特殊なプランナーチームがあるそうで、主に新規カードの設計やバランス調整を担当する、いわゆるカードの生みの親。

AIチームのプランナーは、基本的にTCGプランナーが担当することになるそうだが、「固有のTCG知識以外にAI開発に必要なノウハウを実作業をしながら身に付けてもらっていて、さらに開発スケジュールの管理も任せている」と鄒氏。



そんな頼れるプランナーと一緒に要件の細分化という手法を提案したという。

プランナー的には仕様を正確に作れないのは、実戦では考える要素が多すぎるため。それこそが不確定性の表れだが、1つ1つの要素自体はじつは簡単だという。それに対してエンジニアは、シンプルな要素単位で実装すればテストもしやすくなると提案した。

これにより、複雑な要件をいくつかの子要件に分割し、各子要件をもとにエンジニアが実装を行う。それらを組み合わせてまた複雑で高度なプレイングを実現していく。

細分化した単純な機能は、テストが組みやすくしっかりテストを行えば有効性と正確性は担保できる。それによって、不確定性は組み合わせ調整のバリエーションにのみ影響。TCGの専門家であるプランナーがそれを受け持つことによって、不確定性がエンジニアの実装にまで影響が及ぶことがなくなるという。


▲要件の細分化に関して、基本的な考え方はエンジニアリングにおけるシステム設計に似ているのでプランナーの持つTCGの理論知識はもちろん、エンジニア的な発想も重要。プランナーとエンジニアのより緻密な連携が求められる。

要件細分化の実例として、デモンストームというカードが紹介された。このカードは、お互いのリーダーとフォロワーすべてに3ダメージを与えるもの全体ダメージ能力を持っている。

鄒氏は、デモンストームを例に全体ダメージにおける運用要件について説明していった。『シャドウバース』で勝利するための基本的な2つの戦術は、相手を倒すことと、味方を生存させること。

全体ダメージは、場に存在する複数カードに影響するので、相手を倒すこと、味方を生存させることの「両方を同時に達成することが望まれる」と鄒氏。そのために要件を細分化、シンプルにしていくという。


▲相手を倒すという大要件は、相手のフォロワーを倒す、相手リーダーの体力を削るという2つの子要件に分割でき、その子要件をさらに分割する。こうして複雑な要件を少しずつ噛み砕いておけば、最終的には信頼度の高いシンプルな仕様作成とテスト構築が可能になる。

要件を細分化してシンプルにしたら、次はテストケースの作成に入る。テストシナリオの設計方法は、「一言でいうと要件と一緒に実戦から生まれる」と鄒氏は言う。

プランナーはもともとTCGの専門家なので、要件を考えるとき頭の中に自然と実戦で起こりうる状況を脳内でイメージする。大抵の場合、そのイメージした状況がそのままテストシナリオとして使えるため、特別な技術やネタはなく、一番大事なのは実戦の経験を積むことだそう。

そして鄒氏は、テストシナリオの実例を紹介した。


▲こちらは"相手リーダーの体力を削る"というケースについて、自陣フォロワーをリーダーに攻撃するという要件。盤面上では敵フォロワーがすべて体力2なので、デモンストームを撃てば一掃できる。その場合の自陣フォロワーの理想的な行動プランは、敵フォロワーの処理をデモンストームに任せて自陣フォロワーは積極的に相手リーダーを攻撃するという方法。


▲次に相手のフォロワーを倒すという要件から分解する例。相手を倒しきれない場合は自陣フォロワーを使うという小要件のテストシナリオについて。先ほどのシナリオと違い、相手の場に体力が4以上の敵が存在し、デモンストームだけでは倒しきれない。そこで自陣フォロワーは相手リーダーを狙わず全体ダメージと合わせて相手フォロワーに攻撃し、それを倒すことがより戦況を有利に運ぶことができるというケース。

以上2つの例が、AI開発においての要件細分化と細分化された要件に対して設計したテストシナリオの実例。このようにシンプルなシナリオを作れたのは「要件を細かくしたおかげ」(鄒)

ここまで来たら、いよいよテストケースを作ることになるが、エンジニアにテストシナリオを渡さなければならないが、先に紹介したシンプルなテストシナリオの遷移図のような資料を作るために30分かかるという。

さらに前に要件細分化の例で分かる通り、1つな複雑な要件は大量な小要件に分割される。つまりテストケースを大量につくる必要があり、資料の量も膨大になる。



元々QAコストの削減を目指している中で、これでは開発の効率が逆に下がってしまう。この面倒な資料作業を無くすためにはどうすれば良いか?

鄒氏は「エンジニア自身がテストシナリオを作成するか、もしくはプランナーにテストケースもろとも作ってもらうか」の2択しかないという。

テストシナリオはプランナーが要件を考えるときに脳内イメージでおのずと出てくる。つまりテストシナリオの設計と要件の作成は分離できないため、エンジニア独自でテストシナリオを設計するのは難しい。

となればプランナーに直接テストケースを作ってもらうしかない。「プログラミングはもちろんできないが、エンジニアのほうで専用のテストケース作成ツールを開発すれば問題はありません」と鄒氏は語った。

続いて、ゲーム機能を流用したテストケース作成ツール「AITestKun」について紹介。

バトル機能を流用したAITestKunは、ゲームのバトル機能をそのまま流用して作られており、開発チームであれば誰でも使えるそうだ。

こちらのツールのメイン機能は、テストケースの登録と再生。登録するときは、テストケースのスタートの盤面と正解にたどり着くための行動を手動で再現する。すると正解の結果が出てくるので、それをスタートの盤面と一緒に保存。

そしてテストケースの再生は、あらかじめ保存したスタートの盤面を再現し、そのままAIに動いてもらうというもの。その結果をあらかじめ保存した正解と比較し、差分があったらNG、完全一致すればOKになる。



▲実際にツールを使っている動画が上映された。

「我々のAI開発では、テストケースのOK、NGの唯一の判断基準は結果です。なぜなら、細かい攻撃の対処の選択順位が自分のフォロワーの行動の順番を変えても最終的に結果は変わらないことが多いため」と鄒氏。

もちろんそれは『シャドウバース』というゲームの特性によるものとしながらも、「それであれば細かい行動まで厳密に定義する必要はなく、AIの人間っぽさを表現したいという目的にもつながる。何よりすべての分岐に対してホワイトボックステストを行う必要がなくなるので、実装エンジニア以外の人でも簡単にテストを行えるようになる」と続けた。



▲プランナー主導のテスト駆動開発のまとめと、紹介された手法導入によって得られた成果を紹介。2019年に入ってからの開発タスク量と開発時間を過去のデータと比較すると、AIチームの開発効率が約2倍に増加し、AI開発がしっかりスケジュールに追従し、遅延を完全になくすことができたという。また、AIのバグ報告数も約25%減少し、システムが安定した。

最後に鄒氏は、「この手法を取り入れられたのは、プランナーとエンジニアの共同作業のおかげです。お互い相手の目線で問題を考える習慣を身に付けることができ、エンジニアがよりTCGの戦術にあわせたアルゴリズム設計ができるようになり、プランナーもまた、要件分析でエンジニアリング思想を取り入れてより洗礼された仕様を作れるようになりました。

これからさらに長期開発に向けて新しい問題も出てくると思うが、チーム一丸となって協力して問題を解決する体制を築けたのは、ある意味一番大きな成果かもしれないと考えています」とまとめた。



ここからは、バトルパートを担当している柴田氏が、スキルの観点からどのようにQAコストの削減と堅牢性の強化をはかったのかを説明していった。


▲『シャドウバース』のスキルは、スキル、タイミング、コンディション、ターゲット、オプションの5つの要素の組み合わせで動いているという。

スキルの仕組みの例として、"冥府への道"というカードを紹介した柴田氏。このカードは、場に存在するとき自分のターン終了時、自分の墓場が30枚以上なら、相手のリーダーと相手フォロワー全てに6ダメージを与える能力。このカードを先の5つの要素に分解すると以下のようになる。



スキル開発では、基本的にこれら5つの要素に対して、新たな振る舞いを追加することで新規実行を行うという。ではこの実装したスキルに対し、どのような形で堅牢性を担保しているのか?

柴田氏は、その為に行っているテストとして、単体テスト、結合テスト、回帰テスト、自動テストの4つが存在していると説明した。


▲単体テストでは、5つの要素ごとにテスト可能なシナリオをエンジニア手動で作成し、テストの実証をしていく。このタイミングでは他の要素との組み合わせは考慮せず、1つ1つ独立したシンプルなテストとなる。


▲結合テストは、単体テストで行っていなかったスキルの最小要素同士の組み合わせのテストを行う。カードのスキルとしてプランナーから要望のあった形で動作が正常かどうかエンジニア側で実装。その後、テストシナリオ作成してテストする。

回帰テストについて、これは以前に問題があった組み合わせのテストシナリオを複数仕様するテストとなる。柴田氏は、回帰テストを行う理由について、「単体、結合テストに関しては元々エンジニア側で行っていました。しかし、スキル開発で最もQAコストが割かれ、バグ報告が最も多いのは複雑なカード組み合わせによるバグであり、それに対する明確な答えがないまま、各バージョンで発生した注視すべき組み合わせを人力でデバックしている状況だった」そうだ。

そしてそれはバージョンを重ねるごとに組み合わせも増加し、デバック工数もそれに合わせて増加。「この複雑なカード組み合わせのバグを減らすことはスキル開発において、QAコストの削減と堅牢性の強化に不可欠だった」(柴田)

しかし、回帰テストにはそもそもテストシナリオ作成に関して2つの問題があったという。

1つはカードの挙動の設定はプランナーが行っており、エンジニアではどのような意図をもってそのカードの動きがデザインされたのか、正確かつ迅速な把握ができないという点。

もう1つはプランナーが複雑なカード組み合わせを正確かつ迅速に算出できたとして、テストシナリオを作成するプログラミング知識がなかったという点だ。



この問題は「お互い教え合いながらツーマンセルで作業すれば可能ではあったが、あまりスマートとは言えない」と柴田氏。

ここでテストシナリオ作成、検証にあたって2つの要件の実現が必要となった。1つは回帰テストの運用前に発生していた複雑なカード組み合わせによって発生したバグ報告を減らすこと。もう1つはテストシナリオ作成に著しく工数を割かせることのない簡単なテストシナリオの作成手段。

これらの事を考えたとき、柴田氏は『シャドウバース』内に再開機能が存在していることを思い出したという。

再開機能とは、バトルが中断されたとき、中断前のバトルに戻る機能で、再開機能を動作させるために必要なプレイログは、バトルを行っている際の操作に紐づいて自動で出力される。

このとき出力されたプレイログをもとに一手一手プレイを再現していき、最終的に中断前のバトルに戻る機能を再開機能という。

このとき出力されるプレイログは、バージョンごとに変動しない性質をもっており、バージョンをまたいでそのテストシナリオを使用可能。過去バージョンで発生した組み合わせバグを修正後、そのテストシナリオを作成できれば以降のバージョンでそのテストシナリオによりロジックの正統性が担保される。

これらを加味しつつ、再開機能をもとに回帰テストツールを作る利点は大きく2つ。1つは再開機能は既存機能のため1からツールを作成する必要はなく、基本的にはコア部分のメンテナンスが不要である点。「これは長期運用を考えるならば必要なことだった」と柴田氏はいう。

そしてもう一つは再開機能のプレイログをもとにテストシナリオを作成することで、テストシナリオのプレイログが出力できるため、面倒な学習コストや手順が不要で『シャドウバース』の知識があれば誰でもテストシナリオ作成ができる。これにより、カードに対して深い知識を持つプランナーがテストシナリオを作成することを可能にした。



これらのことから柴田氏は、再開機能をもとに回帰テストツールを作成することを決断したとのことだ。そして回帰テストツールで保証したいことは、新規実装、ソースコードの改修、リファクタリングの結果、以前と挙動が同じであることを挙げた。

行動変更前に作られたプレイログはそれまでのバトルの結果であり、そのプレイログをもとに同じ状態に再開できていることを確認できれば、以前と同じ結果を得られている。つまり既存機能を破壊していないことが保証される。

ただ、通常のプレイログにはその結果にかんするログが存在しないため、回帰テストツールを使用した際に再開後に結果が同じであるという判定を行うため、テストシナリオとして使用するプレイログに再開用の情報とは別に情報を足す必要があった。


▲必要な情報は以下のとおり。この追加情報をもとに挙動の差分をチェックする。

回帰ツールで必要な情報の記載と、それを使用したチェックタイミングはユーザーの任意のアクションに対してスキルの発動が内包されていく形になる。各スキルの終了タイミングで追加情報の記載、チェックを行う。

なぜ、このように細かいタイミングで情報の記載とチェックが必要なのか? それは「スキルのテストにおいて、過程と結果が重要だから」と柴田氏。

結果が合っていれば、過程が途中でズレていても良いというテストをゲームのコア部分を担うスキルで行ってしまうと、その余波が多岐にわたって影響を及ぼし他のバグを誘発しかねない。テストの過程を無視してテストしてしまうと結果の保証が得られなくなってしまう、というわけだ。



次に柴田氏は、回帰テスト用のテストシナリオの作成方法の流れと、作成されたテストシナリオをもとに正常パターンと異常パターンを提示しながら回帰テストをどのように行っているか説明した。

回帰テスト用のテストシナリオを作成する方法は、テストしたいカードの組み合わせをプレイし、プレイログを保存するだけで完了となる。基本的には通常通りにゲームをプレイすることでテストシナリオが作成されていく。

そして作成されたテストシナリオをもとにテストを実行するときの流れ。こちらは相手の場に体力1のカードのみ存在する状況で、1ダメージを与えることができるカード、相手の場の体力1のカードに対して発動したとき相手の盤面が空になる、というテストシナリオの正常パターンと異常パターンを紹介。ここではチェックタイミングで
記録時と差分がないかを確認する。


▲実際に差分が発生すると、回帰テストツールではエラーログが発生。エンジニアがこのログを使用して、バグが起こっている箇所にあたりをつけていく。

最終的に修正を試みていった結果、回帰テストツールで該当テストシナリオを実行した際にエラーログが発生しなくなり、情報のチェックで不一致がでなくなればテストが正常に通過したことになる。エンジニアはこれらの工程をソースコードの変更が加わる度に行っているそうだ。

また、開発中はプランナーが作成したテストシナリオすべてをチェックしてからソースコードのマージをすることを義務付けているとのこと。


▲回帰テスト用に作成されたテストシナリオはバージョンごとにフォルダ分けして管理している。これはカードのパラメータやスキルがバージョンをまたいで変更されたとき、ロジックは正常動作しているがエラーを吐き出してしまうシナリオが発生してしまうため。

発覚済みの組み合わせバグに対しては人力でのチェックの代わりに回帰テストを使用することでその正当性が担保された。柴田氏は「既存の開発で行ってきた人力デバックの結果を損なわず、QAコストの削減とより強固な堅牢性が担保できた」と考えている。

ただ「回帰テストの過程と結果を担保する特性により、ある程度の堅牢性は担保できるようになったが、こちらで想定していない挙動のバグに対しては人力で見つけるしかない」点に関して不安が残ったという。

この問題に関して、何とか人的コストをかけずに未発覚バグを検知することができないかと考えた結果が自動テスト、つまり網羅的自動デバック機能というわけだ。



網羅的自動デバッグ機能は、4つの機能をサポートしている。まずモンキーテストは、ランダムのタッチ操作を行い、シーン遷移やタッチ操作によるエラーが発生していないか重点的にチェックする。

次に自動デッキ編成機能とAI同士の自動バトルデバッグ機能について。これら2つの機能を合わせることで自動バトルデバッグが可能となるという。

自動バトルデバッグ機能は、バトルシーンのデバックに特化した機能。1バトルごとに自動デッキ編成機能で作成されたランダムなデッキを編成し、網羅性と偶発性の高いAI同士の自動バトルを行わせる機能となる。




最後に社内SNSへの自動レポート送信機能について。こちらはこれまで紹介したモンキーテストや自動デバッグ機能の起動中、何かしらエラーが発生した際のエラー内容を社内SNSに自動投稿する機能で、バグの特定を助けるための情報が付与されている。



▲高頻度でバグ報告されるカードや未実装が判明しているカードに関しては、ウェブ上からNGカードとして登録することで自動デバッグのデッキ編成時にリストから除外され、自動デバッグで使用されなくなる。これにより無駄な自動デバッグな報告が減り、有益な報告のみ社内SNSに投稿されるようになったそうだ。

柴田氏は、これら網羅的自動デバッグ機能を使用することで「回帰テストでカバーできなかったチェックリストから漏れたバグの検知や開発初期に発見される低レベルなバグの早期検知を、人の手を介さず発見することが可能になった」と語る。

また、網羅的自動デバッグ機能が実装されたことで、それら機能をフル活用したパフォーマンスチェックを手軽に行うことが可能になったそうだ。

そして、スキル開発においてこれらテスト手法導入により得られた成果として、「最も大きな成果は、バトル全体のバグ報告が実際にテスト駆動開発を導入した1.6.0~2.4.0までの間において、約40%の減少を見せたこと」と柴田氏。

もちろん1.6.0から実装項目を減らしたりスケジュールを遅らせたことは行っておらず、スキルの組み合わせ数とカードの枚数は現在も右肩上がりで増えている。「その中でこの成果を得られたのは大きい」(柴田)とのことだ。



柴田氏は、「我々はカードの継続的な増加に対し、堅牢性の低下とQAコストの増加が課題になり、対策としてテスト駆動開発の導入を検討した。AIとスキルの両方での導入に対して課題があったが、AIでは不確定性に対してAI要件の細分化とプランナーによるテストケース作成を手厚くサポートすることで、AIの有効性、正確性を担保した」とコメント。

スキルにおいては、回帰テストにより既存の組み合わせバグの再発を防止しつつ、網羅的自動デバッグ機能を使用することにより、人の手を介さずにバグの検知が可能になることでQAコスト削減、堅牢性の強化を実現。

またAI、スキルの両方においてテストツールの開発に既存の機能を流用することで実装コスト、学習コスト、メンテナンスコストを抑えることに成功した。

そして最後に「『シャドウバース』は10年以上続くタイトルを目指しています。今回紹介した手法は、この基礎になると我々は強く確信しています。最終的にはユーザーの皆様に最高のコンテンツを届ける。それを実現するため『シャドウバース』の運営は日々努力を続けています」(柴田)とメッセージを送った。