毎週リリースを実現するテスト活動

こんにちは。 品質向上グループの茂呂一子(@ichiko_revjune)です。

クックパッドアプリは、サブミット・リリース作業を自動化して、アプリを毎週サブミットするようになりました。これを実現するリリースフローについては、 クックパッドアプリはみんなが寝ている間にサブミットされる で紹介しました。

このリリースフローを実現していく過程では、「機械に人間があわせる」という方針で、サブミット・リリース作業が自動化されていきました。つまり、毎週サブミット・リリースをするためには、何をどのように自動化するべきかという視点で自動化する対象が決まっていきました。

アプリは開発が終わればすぐにリリースできるというものではありません。この記事では、リリース前のテスト作業をどのように調整して、毎週リリースを実現しているのかを説明していきます。自動サブミットの導入はiOSアプリが先行したため、ここではiOS版クックパッドアプリについて説明します。

自動サブミット導入以前のリリース前テスト

この記事 にあるように、以前のリリースフローでは、開発期間、コードフリーズ、テスト期間を経てリリースをしていました。このテスト期間に行うテストをリリース前テストと呼びます。テスト期間は、3〜4営業日でした。

リリース前テストの内容は大きく3つです。

ひとつめは、UI操作を伴うシナリオテストを複数のテスト環境(iOSデバイスとiOSバージョンの組み合わせ)で実行することです。このシナリオテストは、Appiumを使って機械的に実行しています。

ふたつめは、自動化がむつかしいが重要な機能を手動でテストすることです。例えば、In App Purchase に関する機能や、写真撮影が必要な機能などです。

みっつめは、各リリースに含まれる変更に関連した機能を手動でテストすることです。変更内容から起こりそうな不具合を想像し、それを実際に確認するというような作業です。探索的テストと呼ばれるものに近いでしょう。

これらを実施して不具合が見つかれば修正し、リリース前にその修正がうまくいっているかを確認していました。

自動サブミット導入のために

自動サブミット導入後もリリース前テストはなくなりません。スケジュールされた自動サブミットが完了し、テスト対象が確定してからリリース前テストが始まります。

先に説明した、以前のリリースフローにあわせて設計したテストをそのまま実施すると3〜4営業日かかることになり、リリース前テスト以外の活動にあてられる時間がなくなってしまいます。わたしたちは自動化したシナリオテストを持っているため、テスト実施以外にも、これらをメンテナンスする時間は必要です。また、テストツールを改善したり、リリースフローを改善するなどの活動もリリースを続ける上では欠かせません。テストのやり方か内容を変更しなければ、毎週のサブミットに耐えられなくなってしまいます。

自動化できるところは自動化し、人間にしかできないことを人間が行うという方針で、テスト作業を効率化してきました。自動サブミット導入当初はサブミットからリリースまで、2〜3営業日かかっていました。しかし、最近は2営業日でリリースできるようになってきました。

幸いにして、大きな不具合を出すことなく、毎週のサブミットとリリースが実現できています。テスト作業をどのように変えていったのかを課題ごとに説明していきます。

一番時間がかかるのはシナリオテスト実行

既に自動化してあった200件弱のシナリオテストは、ひとつのテスト環境(iOS デバイスとiOSバージョンの組み合わせ)での実行に10時間以上かかっていました。加えて、以前はシナリオテストをCIマシン上で実行させる為の環境整備が追いついておらず、手元のPC上で実行していました。そのため、毎晩の就業時間外にひとつのテスト環境を選び、実行していました。

リリース前テストでは、iPhone/iPadいずれの環境でも動かすことと、サポートiOSバージョンを網羅することを満たすよう、複数のテスト環境で実行します。したがって、1リリースあたりのシナリオテストにかかる時間は、10時間かけるテストする組み合わせの数でした。

これらの問題はCIマシンでの実行と、シナリオテストの並列実行という方法で実行時間を短縮しました。

今年に入ってから、CIマシン上で実行することは試みていました。そして、自動サブミット導入の頃に準備が整い、本格的に実行をCIマシンに任せるようになりました。シナリオテストを実行しているCI環境はビルド用のCI環境とは別のものを使用しています。理由はふたつあり、ひとつめは、実行にかかる時間が長いため短時間で終了するビルドタスクと混ぜて実行するべきでないためです。ふたつめは、最新のOSでは動作が不安定になりやすく、ビルド環境と同じタイミングでOSを更新できないことが多いためです。

シナリオテストの並列実行は、今年チームに加わった加藤が、実行の高速化を目的に実現してくれました。並列実行と呼んでいるのは、同じデバイスとiOS を使用するiOS Simulatorを複数起動し、別のシナリオを同時に実行することです。UIテストのボトルネックのひとつにSimulatorを操作する時間があるため、Simulatorを増やすことに効果がありました。これによって、1つのテスト環境でのテスト実行にかかる時間が約3分の1になり、実行時間の総量も同じように少なくなりました。

実行時間の短縮という他にも、金曜日から日曜日にかけてシナリオテストを実行するようスケジュールして、実行開始が遅延してもシナリオテストが終わるのを待つ時間が発生しにくいように工夫しています。自動サブミットは金曜日の早朝に動きだすので、順調にいけば金曜日の午後にはシナリオテスト結果がそろい、レポートを見れるようになっています。

シナリオテスト実行の指示を毎回人間がしていた

シナリオテストは、1回のリリースのために複数のテスト環境で実行しています。テスト環境は固定しておらず、リリースごとに変え、ある程度の期間でみたときに、iOSデバイスサイズとiOSバージョンを網羅するように設計してきました。

自動サブミット導入以前は、このテスト環境の選定を人間が行い、実行のたびに指定していました。

自動サブミット導入後は、このテスト環境の選定をスクリプト化し、実行のたびに指定しなくて済むようにし、機械による無作為抽出を導入しました。

機械に任せる領域を増やして、リリース前テストの準備をひとつ減らしました。

お手本画像を人間が更新していた

シナリオテストツールには、表示くずれを見つけるために、シナリオテスト中で取得したスクリーンショット画像をお手本画像と比較して、差分を表示する機能があります。

このお手本画像の管理には2つの課題がありました。ひとつめは、テストツールの実行環境ごとにファイルを管理しており、すべての環境で同じファイルを使っている保証がなかったことです。ふたつめは、人間が差分画像を見ながら更新すべきファイルを探し、コピー&ペーストでお手本画像を更新していたことです。実行環境が複数存在したため、特定の環境への反映漏れということも起きていました。

この作業を改善するにあたって、まず、お手本画像はAWS S3に一元管理するようにしました。実行のたびに、S3から最新のお手本画像を取得し、どこでも同じお手本を使用するようにしました。

次に、更新作業の一部をスクリプト化し、更新するべきかの判断だけを人間が行うようにしました。人間は差分画像の一覧をみながら、更新する画像にマークをつけます。その選択結果をファイルに出力し、それをスクリプトに与えて実行すればS3上にファイルが送信されます。

単純作業を機械に任せることで、人間は不具合の探索に集中しやすくなりました。

シナリオテスト結果から不具合をみつける手助け

シナリオテストは、UI操作を伴うため、不具合がなくてもシナリオが失敗することがあります。本当に不具合があるのかは最終的に、人間が実機を操作して判断することになります。その失敗が不具合の可能性が高いのか、低いのかを知ることで、この再操作を減らすことができます。

失敗しやすいシナリオや不安定なシナリオを見つける目的で、シナリオごとの実行結果を蓄積、可視化するアプリケーションを構築しました。このアプリでは、同じバージョンのアプリに対する複数のテスト環境での実施結果の成否を一覧できます。「どのテスト環境でも失敗しているので不具合の可能性が高い」「ひとつの環境だけ失敗しているので不具合の可能性が低い」といった具合に参考情報を簡単に見つけることができるようになりました。

f:id:ichiko_revjune:20181212111114p:plain
シナリオごとの実行結果を蓄積、可視化

このアプリがない頃は、複数のレポートを開いて見比べていました。成功失敗というデータに絞って可視化することで、ずいぶんと容易に理解できるようになりました。

自動化できない手動テストの効率化

自動化することはできないけれど重要な機能、例えば In App Purchase に関する機能は毎回手動でテストをしています。リリースごとの追加機能を対象とするテストではないので、ほぼ内容は決まっています。テスト作業の見直しを始めた時点では、削ってしまえる機能もありませんでした。

これらの手動で実施するテストの項目は、厳密なテスト手順を定めておらず、この機能でなにができること、という満たすべき項目をリストにしています。探索的テストのチャーターのようなものでしょうか。

自動サブミット導入以前も、関連機能に変更がなければ省略してもよい項目はあり、省略することもありました。自動サブミット導入後は、これを厳格に適用して、関連機能に変更がなく不具合が発生しないであろう機能へのテストを省略するようにしました。合理的にテストしすぎない工夫としては、うまくいっている方ではないでしょうか。

これからの課題

小さな改善を重ねてリリース前テストに時間をかけ過ぎることなく、毎週のリリースを実現している方法を紹介しました。

サブミット自動化後のリリースフローは、リリース前テストで致命的な不具合が見つかった場合、リリースをあきらめるルールです。このフローがうまくまわっていくためには、不具合が入りにくいしくみや、機能変更をマージする前に不具合に気づきやすくするしくみが必要です。そのためには、開発チーム内のテスト技術を向上させることも必要でしょう。これらの点ではまだ効果的なアクションを取れていないので、急がず確実に小さな変化を積み重ねていきたいです。

/* */ @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;*/ /*}*/