新規決済手段導入に際し、なるべく丁寧にテストケースを作成した話

会員事業部の日高尚美(@natan3)です。 半年前になりますが、クックパッドでは Android ユーザ向けにプレミアムサービスの決済手段の一つとして Google Play 決済を導入しました。

ユーザに新たな機能を提供する前には、何らかの形で開発者側での検証が必要です。

Google Play 決済導入バージョンのリリースは、ユーザのお金を扱うこともあり、不具合が起きた際にサービス全体の信用に関わる、非常にリスクの高いリリースでした。 それに伴い、検証もできる限り万全に行わなければなりません。

そのため、なるべく丁寧にテストケースを作成し、それをもとに検証を実施することで新機能が期待通りに実装されていることを担保しました。 丁寧にテストケースを作成したから、というだけではもちろんありませんが、リリースから半年経った今でも Google Play 決済周りの目立った不具合はまだ見つかっておりません。

今回作成したテストケースの紹介

今回作成したテストケースの一部をご紹介します。 実際に利用したものと表現を変えてはいますが、雰囲気は伝わるかなと思います。

f:id:nano-041214:20180718194510p:plain

含まれている項目は以下のとおりです。

  • 各画面で起こりうる状況の組み合わせ(上図で言うところの前提条件)
  • 前提条件を再現するシナリオ
  • シナリオを達成するための手順
  • 手順に対応した期待する振る舞い
  • 期待する振る舞いが得られたかどうかのチェック欄

これを元に動作を確認しました。

それぞれのケースにて、想定した通りの画面が表示されていれば問題ありません。 しかし、実装によっては、期待する振る舞いが得られない場合も出てきます。

テストケースにて期待する振る舞いが本来あるべき姿なので、その場合には実装に手を入れる必要があります。 すべての操作に対して期待する振る舞いが得られる状態にすることが、テストケース作成の目的であり、検証のゴールとなります。

Google Play 決済のテストケース作成までの流れ

なにもないところからいきなりテストケースを作成することは難しいため、 画面遷移図とそれらの分岐条件、各 API の返す異常系一覧をもとに、テストケースを作成しました。

テストケースを作成する流れは以下のようになります。

  1. 各画面で起こりうる状況を整理する
  2. 前提条件を再現するシナリオを作成する
  3. そのシナリオをなぞるための手順を埋める
  4. その手順を行うことで期待されるアプリの振る舞いを埋める

以降の文章で、各項目について解説します。

各画面で起こりうる状況を整理する

テストケースにおいて重要なのは 網羅性 です。

そのため、画面遷移図の各分岐である API 接続箇所や画面遷移時にて起こりうるユーザ状態など、前提条件を構成する各状況を洗い出します。

実際の遷移図ではありませんが以降の理解のために Google Play 決済導入時の画面遷移のイメージ図を添えておきます。

f:id:nano-041214:20180718194451j:plain

Google Play 決済導入プロジェクト初期リリースではクックパッドにログイン済みの無料ユーザのみを対象としていたため *1、 各分岐において以下のような状況の組み合わせを、検証すべき条件として考えました。

  • ユーザの状態がどうか
    • ログイン済みユーザ or ゲストユーザ
    • プレミアムサービス会員ユーザ or 無料ユーザ
  • Android のクックパッドアプリのバージョンが決済対応バージョン以降かどうか
  • 決済可能端末かどうか
    • クックパッドがプリインストールされているらくらくフォンなどの場合、Google Play ストアアプリがないため Google Play 決済も利用できない
  • 異常な操作をした場合でも、何らかの方法で本来あるべき状態に復帰可能かどうか
    • この画面を表示している状態で Web からクックパッドのユーザ登録を解除してみる
    • この画面を表示している状態で Web からクレジットカード決済でプレミアムサービスになってみる
    • ここでフライトモードにしてみる

もちろん全ての組み合わせが成立するわけではありません。 例えば決済可能端末かどうかについては、決済不可能端末を伝える画面にて遷移がストップするため、以降の画面については考えない、といった具合です。

前提条件を再現するシナリオを作成する

それぞれの状況が洗い出せると、それらを組み合わせることでユーザが何をしようとしたかのシナリオが書き出せます。

状況の羅列にはなりますが、シナリオを作成しておくことで見通しが良くなり、仕様の考慮漏れについて気づきやすくなります。

例えば、

「ログイン済みユーザが Google Play 決済用画面を開いた状態で Web からクレジットカード決済でプレミアムサービスになった場合、
 Google Play で決済するボタンを押すと既に課金済みであることを示すダイアログが表示される」

といったものです。

そのシナリオをなぞるための手順を埋める

シナリオまで埋め終わると安心してしまいがちですが、書き手以外が再現可能なレベルで手順を埋めるまでがテストケース作成です。

テストケースは、一度作成すると、製作者本人が望もうが望まなかろうが再利用される可能性が高いです。 現にクックパッドでは、作成されたテストケースは今後のテストケース作成の参考にできるよう、社内で共有されています。

コードや文章に限らず、テストケースも、書いた本人ですら暫く経つと書いた内容やなぜこう書いたかを忘れがちです。 テストケースが雑に書かれていた場合には、この記述が当時何のために書かれていたのかを考古学する必要が出てきます。

そのため、なるべく丁寧に書きましょう。

先程の

「ログイン済みユーザが Google Play 決済用画面を開いた状態で Web からクレジットカード決済でプレミアムサービスになった場合、
 Google Play で決済するボタンを押すと既に課金済みであることを示すダイアログが表示される」

というシナリオの例に対しての手順を具体的に書くと、

  1. 無料ユーザでログインした状態でアプリのトップページを開く
  2. サイドメニューのプレミアムサービス会員登録導線をタップする
  3. Google Play 決済を利用するボタンを押す
  4. ブラウザアプリを起動し Web からクックパッドのトップページにアクセスする
  5. Web から先ほどと同一のユーザでログインする
  6. Web のトップページのプレミアムサービス会員登録導線を開く
  7. Web の登録ページからクレジットカード決済を利用してプレミアムサービスに登録する
  8. アプリの画面に戻り、プレミアムサービスに Google Play で決済するボタンを押す

といったものになります。

その手順を行うことで期待されるアプリの振る舞いを埋める

こちらも先程の手順同様、丁寧に書く必要があります。

先程の手順の例に対応するアプリの振る舞いとしては以下のようになります。

  1. 無料ユーザ向けのトップページが表示される
  2. プレミアムサービスを訴求する画面が表示される
  3. Google Play 決済用の画面が表示される
  4. Web 版のクックパッドのゲスト向けページが表示される
  5. 先ほどと同一ユーザでログインしたトップページが表示される
  6. Web のプレミアムサービスを訴求する画面が表示される
  7. プレミアムサービス登録完了ページが表示される
  8. 既にプレミアムサービス登録済みであることを伝えるダイアログが表示される

異常系であれば、どのような操作をすれば正常系に復帰できるかを伝える画面が出ていることを期待します。 そのため、ある操作の流れで何らかの異常を伝える画面を見たユーザが、その内容を読んだ際に混乱しないかについても確認ができます。

テストケースを作成して得られた良い副作用

テストケースを作成して得られる一番の良い副作用は、仕様の考慮漏れに気づけることです。

テストケース作成前は、Google Play ストアによる決済用システムダイアログが出ているときにブラウザアプリから別な決済手段にてプレミアムサービスを登録したらどうなるのか? というケースについて考えられていませんでした。

Google Play ストアの決済用システムダイアログが出てから決済処理完了までは、クックパッドではその経過状況を知ることが不可能です。 そのため、残念ながら決済完了時に Google Play の購読情報をクックパッドに送る際に二重課金が起きていることを伝えることになります。 幸いにも既に別で考慮していたケースと同様にユーザに重複課金を伝え、問い合わせを促す画面を表示できるような実装になっておりました。

また、テストケースを作成することで、検証の手順の理解や進捗が属人化しなくなるため検証を分担したりダブルチェックしたりできます。

加えて、きちんとやったから大丈夫、という安心感がえられます。

もちろんリリースして運用に入るまで何が起こるかはわからないですが、 最大限やることはやった!という安心感を持ってリリースできるので精神衛生上良いです。

テストケース作成期間について

テストケース作成に着手してから、検証し、修正完了するまでに 1ヶ月ほどかかりました。 開発期間全体のおよそ 1/3 もかかってしまった理由は、テストケース作成と並行して API 実装を始めとした他の作業などもやっていたためです。

しかし、効率的な開発を目指す上で、必ずしもテストケース作成期間を短くする必要はないと考えています。

というのも、仕様を煮詰めながらテストケースも整理していくことで、結果的に考慮漏れによる実装の手戻りを減らすことができるからです。 仕様を煮詰めている段階でテストケースも同時に作成していくことは、回り回って効率的に開発を進めることができると感じました。

最後に

検証を怠ることは、ユーザに検証をさせることと同義です。

もちろんすべてのケースを想定したテストケースを作成するのは不可能です。 しかし、ユーザにサービスを提供する以上、リリースまでに最善をつくすことに価値があると考えております。

テストケースは技術部品質向上グループチーム(以下 QIT: Quality Improvement Team)と密に協力して作成しました。 QIT はクックパッドのアプリを利用したユーザが技術的な問題で残念な思いをする体験を減らすための専門家集団です。

このように、クックパッドでは新機能リリースプロジェクトのために様々な分野のエンジニアが一丸となって取り組みます。

そのため、クックパッドではアプリケーションの品質向上に興味のあるエンジニアや、企画から、実装、テストケース作成までを一貫して行うエンジニアリングに興味のあるエンジニアを募集中です。 興味がある方は採用ページまで!

*1:現在はクックパッドに会員登録、もしくはログインしていないユーザでも Google Play 決済を利用してプレミアムサービスを利用できます

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/