始めに
開発チームの多くは、テストの自動化を、ソフトウェアデリバリをスピードアップする手段と考えています。チーム内のボトルネックがそこにある、と思われることが多いためですが、開発プラクティス全体をより深く検討すれば、もっとよい結果を得ることができます。
バグを防ぐ
テスト、特にUIレベルでのテストの自動化は、ソフトウェアデリバリのパイプラインの最終段階で実施される傾向があります。そこでは一般的に、ライブ環境に入り込んでエンドユーザに悪影響を与えるようなバグの捕捉が行われます。ここでは、テストによってバグの症状(symptom)を検出します。開発者がデプロイする修正は、その治療(cure)ということになります。あたかも、自分たちのシステムが病気になるのを待って、何かをしようとしているかのようです。
このアプローチはチームにとって効果的ですが、現在の作業環境は、私たちに、より少ない人数で、より速く、より多くのことを行うように求めています。ですから、このアプローチを今後も長く続けることはできません。治療ではなく、予防が必要となるのは、このような理由からです。
システムの構築方法を修正することで、問題が発生する前に検出することが可能になります。さらに進んで、最初からバグが発生しにくくすること(予防)もできるのです。つまり、後になって原因を解決するのではなく、バグの発生を防止する、ということです。昔の諺にもあるように、予防は治療に勝るのです。
テスト自動化への旅
私が最初に手がけたのは、VOD(ビデオオンデマンド)プロダクトの開発と管理を行っていたモバイルチームでした。当時、私たちのテストはすべて手動で実行されていました。各プラットフォームのリリースは、平均で年間2~3回に過ぎませんでした。もっとスピードアップしたいと思っていたのですが、リリースにおいて最も明白なボトルネックがテストだったのです。各回帰テストサイクルには約2週間が必要でした。ただし、問題が見つからなかった場合は、です。問題が見つかれば、開発チームが問題を理解し、修正方法を決定し、それを適用する必要があります。これによって、すでに実行されたテストが無効になる可能性があるため、プロセスを再開しなければならず、テストサイクルに2倍の時間を要するのです。
そこで私たちは、UIテストをより自動化する検討を始めました。最初は小さな部分から初めて、自分たちが望む方向に進むことを確認したいと考えていました。また、まずは新しい機能のみを対象として、効果が証明されたならば、システムの既存の領域または既知の問題領域の自動化を検討したい、とも思っていました。
チームとして、私たちが何を作りたいのか、その機能のための重要な受け入れ基準が何であるべきかを理解するために、3つのアミーゴを使用しました。これによって、機能をどのように分割するのか、ユーザが何を自動化するのかについて、出発点を得ることができたのです。
そこから、テストの自動化に使用可能なツール(Calabash、最終的にはAppium)を特定し、実環境でテストを実行しました。私たちはこれを、エミュレータやシミュレータではなく、実際の携帯電話で行ないました。結果として、モバイルデバイスをより有効に活用できるような、独自のデバイステストファームを構築することができたのです。
詳細については、私の一連のブログ記事を参照してください。このシリーズは、ユースケースを特定した"Automating BBC iPlayer mobile testing part one: 3 amigos"、オートメーションプロセスを取り上げた"Part two: automation"、そして"Part three: legacy vs new features"の3部で構成されています。
テスト自動化によって実現したメリット
最初は、自動化の大きな支援によって、シンプルなシナリオを迅速かつ信頼性を持って実行し、必要なフィードバックを短期間で得られるようになりました。しかし、時間が経過し、最初に一連のバグが発見されてしまうと、発見できるイシューの数が段々少なくなり、それを探すような自動化テストケースを、意識的にコーディングしなければならなくなりました。
また、いくつかのシナリオが自動化できなかったために、イシューがまだ解決していない点にも気付きました。例えば、使いやすさに関連するものは、すべて手動でテストする必要があったのです。これらのことから、いくつかの重要なシナリオを自動化して迅速に実行する、ハイブリッドソリューションにたどり着きました。例えば、明らかな問題が発生していないことをチームに知らせたり、新たな機能の予備的なテストを実施して、それが適切であれば自動化するのです。このように、テストは難しいものです。テストを実行しようとして間違いを犯したり、手作業で行う上で時間が掛かり過ぎたりすることは、よくあることです。
自動化の過程において間接的に得られた、予期していなかったメリットは、リリースが早くなったことによって、達成しようとしていることに以前より集中できるようになった、という点です。結果として、新機能を小さなチャンクに分割し、独立して作業することが可能になり、自動化が実現するとともに、それらのチャンクを運用環境にすばやくリリースし、実際のユーザから現実的なフィードバックを得ることができるようになりました。自動化のシナリオを特定する方法を試していた最初の頃は、これはまだ明確ではありませんでした。チームの不注意からしてしまったことは、後にならなければ分からなかったのです。簡単に言うと、私たちは、私たちの仕事をエンドユーザ価値の小さなバッチに分割するようになった、ということです。
開発ライフスタイルの調査
私たちはやがて、自動化されたUIテストでは期待どおりの結果が得られない、ということに気付き始めました。このため、自分たちの開発プロセスの他の部分を見て、何か改善ができるかどうかを確認するようになりました。しかしながら、チームとしての私たちの問題のひとつは、プロセスが身近すぎて、何がうまくいっていないのかを客観的に見ることができなかったことでした。これを克服するため、私たちは、アジャイルコーチによる支援を仰ぐことにしました。実際には、2人のコーチを導入しました。 ひとりは、チームが採用しているプロセスの理解を支援するためで、もうひとりは、エンジニアが実際のシステムを構築している方法について理解を深めるためです。
彼らは、チーム外部の視点から、誰にも気兼ねすることなくシステムの一部を突くことができました。そして、私たちに簡単な質問をして、作業方法の背景になっている理由を確認させることで、"いつもこの方法で行っている"という私たちのサイクルを打破してくれたのです。例えば、私たちが作業の管理に使用するスタンドアップボードには、バックログの欄として、"次(next)"、"開発(dev)"、"テスト待ち(waiting-for-test)"、"テスト中(in test)"、"完了(done)"といった一般的な列がありました。私たちのコーチは、なぜこれらのコラムで仕事を積み上げさせたのか、なぜ開発とテストを2つの異なる活動と見なしたのか、と質問することで、新たな気付きを与えてくれました。コーチのアプローチは、単に私たちのプロセスを変えるのではなく、それが引き起こしていた問題("next"や"waiting-for-test"として、隠れた形でキューに留まっている、未リリースの価値)を見出すことを支援してくれたのです。結果としてチームは、ウォークスルーを通じて"dev"と"test"の列を廃止し、単純で自明な"in-progress"という列に替えることができました。In test columnに寄稿した私の記事では、この作業方法の移行によるメリットについて詳しく説明しています。
私たちが学んだこと
アジャイル開発プラクティスという観点から、私たちが発見した最大の問題のひとつは、私たちのチームには多くの"盲目的な乱用(cargo-culting)"があった、ということです。スタンドアップを実行して、小規模チームで活動して、スプリント単位でリリースしているだけでは、本当にアジャイルであるとは言えないのです。それは単に、私たちが"アジャイル"であるかのように見せかける、いくつかのセレモニに過ぎません。なぜそれをしているのか、さらには、それに何のメリットがあるのかさえ、全員に十分な確信があったのではないことが分かったのです。私たちが最初にしたことのひとつは、アジャイルであることの意味を明確にすることでした。それは客観的なフィードバックに基づいた持続可能なソフトウェアの提供であって、可能な限り速く行動しようとするのではなく、可能な限りのリリースを実行し、ベストを尽くすということです。私たちは読書会を通じてこれを行い、チーム内での共同理解を実現するためにチームディスカッションを進めました。これによってチームメンバは、アジャイルプラクティスの背後にある原則をより深く理解し、自分たちの仕事の方法において、より良い決断を下すことができるようになったのです。
さらに私たちは、実際にシステムを構築する方法についても、コードレベルでの検討を始めました。開発者がコードをコミットするタイミング、コミットの頻度、コミットの大きさの視覚化を試みたのです。これは、開発者を詰るのではなく、彼らがグループとしてコードベースにどのような影響を与えたのかを理解し、より生産的な開発者の習慣を奨励するための試みでした。例えば、一日の終わりに大規模なコミットをするのではなく、小さく、目的が明確で、定期的なコミットを行うような習慣です。大規模なコミットを行ったのであれば、それもOKですが、他の開発者にその理由を説明すれば、彼らもそこから学ぶことができます。
チームに対する私たちの最大の変更点のひとつは、ペアプログラミングを奨励したことです。その結果、機能を単独で開発する開発者は誰もいなくなりました。これはコードレビューを早めましたが、それと同時に、責任を負うべき場合において、手っ取り早い方法を取るようなこともほとんどなくなりました。さらに、チームの若年メンバのスキルと知識をより短期間に向上させることが可能になり、多数のベテランメンバがダミープロジェクトをレビューしていた従来の方法に比べて生産性が向上しました。
より生産的で健全な開発ライフスタイルのために
チームとして活動する中で、生産的で健康的な開発プロセスとはどのようなものなのか、明らかにしてください。このような議論を始める上で有用な方法のひとつが、チームビデオクラブの設立です。これによってチームは、日々の活動から多少の時間を割いて、新しいツールやソフトウェア構築のアプローチについて学ぶことができます。各セッションの最後には、セッションリーダ(プロジェクトマネージャ、技術リーダ、あるいはアイデアをチームに紹介した人)がチームディスカッションを行い、その概念を使用してチームが新しい何かを試す方法を探ります。
その上で、結果がどうあるべきかについて明確な考えを持って取り組むため、ひとつの概念を選択します。"よりよいユニットテスト"という例を取るならば、ユニットテストはチームにとって何を意味するのか、ということです。よりよいユニットテストを行うことで、チームが手に入れるものは何でしょうか。その答を得たならば、どうすればそれを達成することができるのか、複数のアイデアを作り出してください。その中から、成果を短期間かつ客観的にテスト可能なものをひとつ選択するのです。採用した新たなプロセスやテクニックが、本当に成果の達成に役立ったのか、あるいは設定された時間枠ではだめだったのか、はっきりさせたいと思うでしょう。よい結果であれば、それは素晴らしいことです。では、そうでなければ、止めるべきでしょうか?もっと続けますか?あるいは、手を加える?また、誰が実際に実験を行うのか、どのようにしてチームの他のメンバに伝達するのか、といったことも決めなくてはなりません。
新しいプロセスやアイデアをチームの中に定着させたいのであれば、全員がそれに関与する必要がある、ということを忘れないでください。そうでなければ、そのアイデアは、困難の最初の兆候で立ち尽くすか、あるいは行き詰まって、恩恵を受けるのはそれに関わった人たちだけだった、ということになりかねません。
著者について
Jitesh Gosai氏は15年以上にわたり、携帯機器メーカからOSビルダ、アプリ開発者まで、さまざまな企業でテストを行ってきました。現在はTV&Radio部門の主任テスタとして、BBCのモバイル、TV、Webプラットフォームチームなどと協力して、彼らのテストアプローチ、チームのDevOpsやその先への移行を支援しています。