「テスト自動化」について

松尾和昭氏(以下、松尾):それではテストの自動化に関して松尾が発表します。今現在、私は海外事業部で主に活動しています。そこでは第二外国語として英語を使っていて、それを主言語としてコミュニケーションを行っているチームのもとで、いろいろとやっています。

その中で、役割としてはソフトウェアのテストやクオリティというものを専門に回っており、ソーシャルメディアではここにあるKazu_cocoaで活動しています。主なOSSのプロダクトとしては、モバイルのテストオートメーションのAppiumのメインコミッターを務めたりしています。

では、まず話に入っていくんですけど、みなさんの中では「すでにテストの自動化されている」「今からしていこうと思っている」「もうしていて今からさらにいろいろとチャレンジングなことをしようとしている」ところがあるのではないでしょうか。

その中での主なモチベーションとしては、例えば、開発のサイクルをより早くしていきたい。いろいろ失敗を早く見つけて、そのフィードバックを受けたい。テストというものを広く言うと、人手によって、あまり確定的に結果が出ないようなものもあったりする、そういうものをより減らしていきたい。

自分たちが理想とするプロダクトラインを開発し、構築していきたい。はたまた、テスト自動化だけではなくて自動化というカルチャーをつくっていきたい。そういうところをモチベーションとして、やっている方々もいるのではないでしょうか。

そのような時に、よく私も経験するんですけれど、あるコミュニケーションが発生します。例えば、2人の開発者がいるとします。1人の人が、「インテグレーションテスト、こういう種類のテストを書いたんだけど、ちょっと見てくれる?」。もう1人の人が、「これはこういうふうにモック(偽物の環境)に置き換えたりしたほうが、より安定したテストが実行できるね」。

もう一方の人が、「うん、それはわかるんだけれど、でも、けっこう実際の環境に近づけたいんだよね、僕は」。Bの人は、「んー、それでもやっぱりこれをこのままやっていくと、けっこうテストは失敗すると思うんだよね」。Aの人がそこで、「僕の思ってるこのインテグレーションテストっていうのは、こういうふうな理解なんだけどね」。

よくこのようにコンテキストがかみ合わず、いろいろなコミュニケーションが発生している、そういうものをよく目にします。

そこでこのセッションでは、そのような合意形成、いろいろな話がかみ合わないところを、どのようにしてコミュニケーションできるようにしていくか、そういうふうな落とし込みの方法。あとは、実際に私の経験した海外プロダクト、もしくは、少し海外プロダクトに参加する前には日本のチームにいたんですけれど、そこではどう適用していたのか、ということを紹介します。

ただ、このようなテスト自動化の話をする時には、ビジネスの話、人のリソース、もう少し人に寄った話、技術的な話、ツールの話、このあたりは避けては通れない課題ですが、今回はそこにはとくに触れずにいこうと思っています。

Scope、テストの対象範囲をどこにするか

ということで、今回、1つキーワードとして設定してるのは「SPLIT」と呼ばれる英語です。

この「SPLIT」は、英語を直訳すると「分割をしていく」。これから話す言葉も、それぞれのいろいろな単語のキーワードを散りばめて、「SPLIT」に落とし込んでいます。

ここから順々に話していく言葉に関しては、みなさんはなにか大きなもの、よくわからない巨大なものを分割をしていくものだ、と理解を進めながら聞いていただけるとよいかと思います。

まず「S」は「Scope」です。ここでは、「どこをテストの対象範囲とするか?」という話をします。

例えばクックパッド、まずはクックパッドを利用するユーザーさんがいて、今回はモバイルに少し特化をするので、モバイルアプリを使っているとします。クックパッドというサービスは、このようなアプリを使ってはいるんですけれど、そのアプリの先はネットワークにつながっています。そこで、ネットワークの先にクックパッドというサーバーが存在して、さまざまなクックパッドのサービスを、ユーザーさんが利用できるようになっています。

このテストの対象というのを、ネットワークやすべて含んだ全体にするのか、はたまた、モバイルアプリだけに焦点を当てるのか。例えば、モバイルアプリのUIフロー。UIフローもモバイルアプリは1画面や2画面だけでなく、みなさんの開発しているものもそうだと思うんですけど、たくさんの画面やさまざまな分岐が存在します。

このようなネットワーク全体を見るのではなく、この画面にある遷移だけにフォーカスを当てるのか、はたまた、ある画面だけに注力していって、その内部コードまで、開発者の方々だとユニットテストやインテグレーションテストを思い浮かべていただくといいと思うんですけど、そういうところに焦点を当てるのか。

このように、テストをする対象をどこまで含めるのか、全部なのか、あるところに焦点を当てていくのか、それとも、もっと内部コードに踏み込んでいくのか。そのような分け方を、1つ「Scope」として一番はじめの頭文字にしています。

Phase、テストのどの段階に焦点を当てるか

2つ目、ここでは「Phase」という言葉を使っています。

何かの開発を行う時に、ある時系列を考えてみてください。何かモノをつくり始めて、それを世にリリースをする。そう考えた時に、どのような開発のプロセスを踏むか。

よくあるのは、このようなV字型で表現される、何をつくるかを決めて、それを実装して、テストして、世に出すというプロセスはよく言われるものです。

ですが今回「Phase」と表現していきたいのはこれではなくて、あるリリースをする点を境目として、開発環境、開発中なのか、それとも、プロダクトにすでにリリースをされている状態なのか、というところで分けます。

この「In Production」という表現に関しては、私が把握しているかぎりだと、2010年頃から使われ始めた言葉です。よくある、昔あった文脈では、A/Bテストですね。A/Bテスト自体が、人に実際使ってもらわないと計測がなかなかできない。そういうものだから、世に出した後にテストをしていこう。そういった概念のもと、「In Production」という言葉が使われ始めました。

ただ最近だと、カオスエンジニアリングと呼ばれるように、実際にプロダクションに投入しながらも、裏側で、例えばサーバーサイド、障害を発生させながらサービスとしては健全に運用できるようにする。そのような概念としても「In Production」という言葉が時折使われます。

このように「どこにフォーカスをPhaseとして焦点を当てるのか」、そういう話も1つテストを分解するうえでは重要なものになってきます。

Level、どのレベルまでオートメーションを進化させるか

3つ目は「Level」です。これは「どこまでテストオートメーションを進化させるか? 深く掘り下げていくか?」という話になります。

テストの自動化という文脈にかぎらず、テストに関しても、何をテストするのか、それをどう実装していくのか、実行するのをどうするか、その結果をどう計測していくのか、このようなプロセスがよくあります。これのどこを自動化していくのか。

はたまた、あるテスト会社が、少し前にブログの記事を公開したんですけれど、どこまでテストを自動化していくのか、テスト自体を自動化するのか。これは車の自動運転ですね。あれの自動化になぞらえて、テストの自動化がどこまでいけるのかというものを、1つ指標として提示したものです。

一番上はマニュアルテスト。よくみなさんが想像しやすい、人手が確認するようなテストですね。そこから、エンジニアがテストコードを書いて実行させるようなもの。そこから、例えばマシンラーニングを使って、ある程度抽象的な表現をした後、あとは機械がすべて補完してテストをしてくれる。そういう粒度で、だんだんと掘り下げていく。どこまで、研究的な挑戦はあるんですけど、挑戦していくのか。そのような難易度のことです。

Size、対象の範囲をどう切り分けて実行するか

次は「Size」。「SPLIT」の「I」は、真ん中の「i」なんですけれど、テストは範囲、「Scope」の中では範囲という表現で、どういうところを対象にするのかということを決めました。この「Size」では、「じゃあ、それを実際にどういう実行をしていこう」「どう切り分けるか?」という話のところです。

例えば、開発者の中には、よく見たことがある図かもしれないです。

テスト自動化を考える時に、ピラミッドという表現をして、どの程度、どういう類のテストがあると、より理想的なかたちになるかを表したものがこの図です。

一番下が、より安定して高速に回すユニットテスト。それから、だんだんと上に行くにつれて、UIが絡んでくる不安定なテストとよく表現されます。この一番上のところに、今回は対象外なんですけど、マニュアルでやるテストが書かれることも多いです。

もう1つ分け方として、少し前、2010年頃にGoogleが「Size」という表現をそのまま使って、ブログをポストしたことがあるんですけど、私もクックパッドのテックブログにそのような表現を掲載したことがあります。実際に行う全部の、すべてのテストを、いくつかの条件を課した状態でどう区分して、どうテストをやっていこうと表現したものです。

ここまでで、テストをする範囲を分解していく。それをどこを対象にするのかという、プロダクトの開発全体を分解していく。それをどこまで深化させていくのか。じゃあ、それをどう落とし込んでいくのかという話をしてきました。

Type、どのような種類の目的でテストを行うか

最後の「T」では、「どのような『Type』の目的を持ったテストをするか?」という話をします。

みなさんはテスト、今まで「テスト」という言葉をここでは使ってきたんですけれど、いろいろな人が想像するテストというのは1つだけではないはずです。例えば、開発者の方々だと、ユニットテスト、インテグレーションテスト、まあ、実装コードに近いところを想像するようなこともあるだろうし。

例えばデザイナーの方々だと、ユーザビリティテスト、ユーザーに近しいところのテストを想像すること、インフラの方々だとパフォーマンがあると思うんですけれど、それをいろいろな方面から区分した図があります。

『More Agile Testing』という書籍から引用したものなんですけれど、テストを目的別に区分したもので、例えば縦軸が技術的な側面なのか、ビジネスがちゃんと満たせてるのかを確認するものなのか。横軸として、開発をガイドしていくようなものなのか、はたまた、製品自体を評価していこうとしているものなのか。そういう区分で分けた、テストの目的別に分けている「Type」というものがあります。

おそらく開発者の方々が想像するのは、ここに、開発をガイドしながらも、技術的にいろいろ実装していって、実装が正しいかを確認していくようなもの。そこからだんだんと一定のストーリーがちゃんとできているかを確認するようなもの。だんだんとユーザビリティに寄っていって、製品自体が本当にユーザー、ビジネス、そういうところに価値のあるかというのを確認していくようなもの。

パフォーマンスはユーザーに直接影響ありつつも、技術的にいろいろなことをしないといけないので、ここらへんに区分されたり、そういうのもあります。

中央に存在しているのは、自分たちの外部のサービスのところをどうテストをしていくか、コラボレーションしていくかというところなんですが、よくあるものだと、Googleログイン、Facebookログインを想像していただけるとよいと思います。これのどこを目的として、テスト自動化だったりを進めていくのか。

More Agile Testing: Learning Journeys for the Whole Team (Addison-Wesley Signature Series (Cohn))

最終的に行き着く場所を描く区分を作る

ということで、1つ重要なこと、覚えておいてほしいコンセプトというのは「SPLIT」、分割をしてくということ。それが範囲だったり、時間的なもの、もしくは、どこまでやっていくか、それをどう区分していくのか、それはテストという表現の中でどういうところに分割されているものなのか、そういうところを考えながら設計をしていく、そういうコンセプトとしての「SPLIT」です。

実際に私は海外プロダクトに関わって、こういうものを使って、実際の第二外国語として英語を主にチームを構成しているグローバルのAndroidアプリに適用してきました。今からは実際にいくつかのアプリの事例を見せながら、「じゃあ、これを使ってどういうところで合意形成をしていったのか?」を話していきます。

まず、前提……、前提まではいかないんですけど、こういうことを合意する前に、いろいろ話し合ってコミュニケーションを取っていくことが、まず必要です。

どういうプロダクトラインを敷こうとしているのか、どういう自分たちは開発スタイルを取っていきたいのか、そういうところをまず話し合った後に、じゃあ、その中でのテストオートメーションというものは、どういうところまで、どういう区分で、何をしない、そういうことを決めていくために、この「SPLIT」というのを使っていきます。

Androidを対象にすると、幸いなことに、Googleが公式なものとしてテストサイズというのを公開しています。このようなピラミッドをS、M、Lというふうな区分に分けるものを公式に公開してるので、最終的に行きつく情報を共有するための図としていろいろな区分をつくっていきました。

まずは「SPLIT」を順々になめていくと、「S」に関しては、大きく4つに区分しました。1つはとくにモックとか、そういう偽物の環境は置かずに、ユーザーが使う環境になるべく近い状態で、テストをしていこうという範囲。そこからUIですが、そういうネットワークなどはとくに制限せずにやっていくような範囲。そこからさらに内部コードに落とし込まれていくものとして、2つ区分を設けました。

Androidの開発者だったら、JVMを対象としたテストなのか、Android APIを使ったテストなのか、そういうところで区分を設けていると言えば、たぶん想像しやすいと思います。どういう「Phase」なのかっていうと、まずはしっかりとつくっていかないといけないというところだったので、開発環境中だけを焦点としました。

「Size」に関しても、実は私が入る前に3段階で、一応オフィシャルに提供されているというのもあって利用していたんですけれど、この「UIテスト」と表現しているところの認識が曖昧だったので、ここを取っ払って、このサイズというのもいくつかの、4つに分けていきました。

それぞれの対応自体は、このような表現でだいたいチーム内は使っているんですけれど、ユニットテスト、これはJVMでやるような高速なところ。

そこから少しずつ大きくなっていって、UI、1つの画面もしくはその前後の画面だけを対象としたもの。

一番上は、ユーザーがなるべく利用するのに近しい環境のテスト。

この区分で、テストを分けて実装していこう、という話をしました。

「Type」はリグレッションですね。不具合なく継続してモノをつくることができるようにしていくことを注力していくために、まずはそこに必要なものだけを引っ張ってきて構築していきました。

理想を掲げることで認識をすり合わせて議論できた

最終的に行きついたのはこの4段階に分けたものなんですが、これをするにあたって、どこをテストしてどこをしないのか、そういうところを実際に、海外の英語ベースの人たちと議論しながらやった資料が、画面の右側のかたちになります。

けっこうな枚数があるんですけれど、これによってやるところ、やらないところ、このレイヤーではこれをやろう、そういう議論ができるようになりました。

ただ、理想を掲げはしたものの、実際としてはまだ一番上のレイヤーのところの自動化までは、手を出せていないです。いくつか技術的な問題もあるんですけど、このあたり興味がある方は、この後の質問の時に聞いてください。

このような区分で認識を合わせることとして、「SPLIT」を柱にいろいろな資料をつくっていきました。とくに日本語ではない環境でこれをやるのはいろいろ大変だったですが、これのおかげでだいぶ認識をそろえることができました。

これは理想なんですけど、日本だとどうなのか。日本のアプリというのは、4、5年、すでにもう世にリリースされて、開発が継続されています。なので、実際にどういう戦略を取っていたのかということは、少し前のtry! Swiftで話したので、そこに発表を渡すとして、三角のピラミッドにマッピングしてみると、このように現状なっています。

技術的な課題がありつつも、中身が、Lのところが少し抜けてる状態になっているんですけど、テストピラミッドというのは理想ですが、実際に適用していくうちに技術的なものにぶつかったりする。そういった対比として、日本のアプリを取り上げています。これにいくつかの手動のテストが加わって、日本のアプリは行っています。

最後、グローバルのiOSなんですけれど、基本的にまだここには手を出せていないです。ただ、1つおもしろいことをやっていて、グローバルのAndroidではこのあたりのテストの「Type」を自動化しようとしていましたが、iOSでは、このパフォーマンスをテストしようとしています。

これは、過去の経験からあるところを境に、ある機能、あるシナリオが著しく性能劣化したという経験があり、そこに関して実際に計測できるようにしていこうとして、取り組んだものです。

実際に自動化して数値が出るようになっているので、ビフォーとアフター、少し文字が小さいんですけれど、3秒ぐらいかかっていたものが平均して2秒ぐらいになりました。

UIレベルからできるように計測をしたり、これをCIに載せて継続して計測をできるようにしたり、そういうものも部分的に取り組んだりしています。

最後、このようなツール、このようなことを実現するために、いくつかザーッとツールを使っているんですけれど、このあたりは後で公開する資料を見ながら、こういうものを使っているのか、使ってないのか、そういうのを見てみてください。

今日は1つの大きなテスト自動化という概念を分割するために、「SPLIT」と呼ばれる1つのコンセプトを提供しました。それぞれの中で、チーム内で分割をして共通の認識を使っていって、それで合意形成を行った後に「これに突き進もう」、そういうコミュニケーションが生まれて、テスト自動化が深化できるといいと思います。

以上で発表を終わります。ありがとうございました。

(会場拍手)