本連載では、AndroidおよびiOSアプリ開発における、システムテストを自動化するツールを紹介していきます。今回は、Calabash-Androidによるテスト実行サイクル高速化の実現や、GPSの操作・スクリーンショットの撮影・ステップの実行タイミングの調整などさまざまな「ステップ定義」、「データ駆動型テスト」を実現するための「Scenario Outline」について解説します。
本連載では、AndroidおよびiOSアプリ開発における、システムテストを自動化するツールを紹介していきます。連載第4回の「iOS/AndroidにCucumberのBDDをもたらすテストフレームワークCalabashの基礎知識とインストール」から数回にわたり、「Calabash」、特に「Calabash-Android」を中心に解説しています。
前々回(連載第5回)の「Calabash-Androidでテストシナリオを作成する方法」では、Calabash-Androidで事前に用意されている「ステップ定義」を使用してテストシナリオを作成する方法を解説。Calabash-Androidのテストで必要になる、各種UIコンポーネントの特定・操作・検証方法を紹介し、ステップ定義の仕方やUIコンポーネントを調査する「console」について解説しました。
前回(連載第6回)の「Calabash-AndroidによるBDDの実践とJenkinsによる『Living documentation』」では、Calabash-AndroidによるBDDの実践を中心に、「Living documentation」で「見せる化」を実現するためにJenkinsプラグインを活用する方法や、タグによるテスト実行対象の特定方法などを解説しました。
今回は、これまでの連載(第4〜6回)に関連した、さまざまなテクニックを紹介します。
連載第4回の『コラム「テストのライフサイクル」』でも説明しましたが、Calabash-Androidの初期設定では、テスト(「calabash-android run {YOUR_APK_FILE}」コマンド)実行時に、テストシナリオごとに次の処理が順番に行われます。
これは、テストの冪等性を実現するという観点では、理にかなった方法の一つです。しかし一方で、この一連のテストサーバーの起動〜停止のオペレーションは、非常に時間がかかります。
例えば、本連載の説明で使用しているサンプルプログラムでも、著者のPCでは、テスト対象アプリのアンインストール/インストールだけで1テストシナリオ当たり平均4秒弱かかっています。
フィーチャー/テストシナリオのまだ少ないプロジェクト初期はさほど気にならないかもしれませんが、フィーチャー/テストシナリオが質・量ともに充実してくるプロジェクト中〜後期では、テストの冪等性の実現以上にオーバーヘッドが掛かり過ぎてしまいます。
その結果、フィードバックサイクルを長くしてしまう主原因になる恐れがあります(フィードバックサイクルの長期化は、メンバーがテストへのモチベーションを失う主要素の一つなので、注視する必要があります)。
以下では、この一連のテストのライフサイクルを変更することで、テストの実行サイクルの高速化を実現する方法を説明します。
テストサーバーの自動起動・停止の設定は、「{プロジェクトのルート}/features/support/app_life_cycle_hooks.rb」に定義されています。下記の箇所をコメントアウトすることで、シナリオごとのテストサーバーの自動起動・停止設定を解除できます。
Before do |scenario| # start_test_server_in_background ←シナリオ開始前に、テストサーバーを起動しないようにします。 end After do |scenario| if scenario.failed? screenshot_embed end # shutdown_test_server ←シナリオ終了後に、テストサーバーを停止しないようにします。 end
一方で上記の設定を行う場合、別途以下の作業を任意のタイミングで実施する必要があります(後述)。
テスト対象アプリの自動アンインストール/インストールの設定は、「{プロジェクトのルート}/features/support/app_installation_hooks.rb」に定義されています(※注)。
下記の箇所(22〜24行目)をコメントアウトすることで、シナリオごとのテスト対象アプリの自動アンインストール/インストール設定を解除できます。
#uninstall_apps #install_app(ENV["TEST_APP_PATH"]) #install_app(ENV["APP_PATH"])
一方で上記の設定を行う場合、別途以下の作業を任意のタイミングで実施する必要があります(後述)。
厳密にはこの処理は、違うシナリオでもフィーチャー名が同じ場合は実行されません。つまり、以下のような場合には、特に上述のコメントアウトをしなくても、テスト対象アプリの自動アンインストール/インストールは実行されないことになります。
しかし、条件や挙動がトリッキーになることを避ける観点から、上述のコメントアウトをすることをオススメします。
上記の設定を行った上でのテストの実施方法は、以下の通りです。
【1】実機の接続/エミュレーターの起動
【2】テスト対象アプリの実機/エミュレーターへのインストール、およびテストサーバーの起動
プロジェクトのルートディレクトリで「calabash-android console {YOUR_APK_FILE}」コマンドを実行し、連載第5回で紹介した「console」を起動します。
$ calabash-android console app/build/outputs/apk/app-calabash-release.apk
consoleで「reinstall_apps」コマンドを実行し、テスト対象アプリを実機/エミュレーターへ再インストール(アンインストール+インストール)します。
irb(main):001:0> reinstall_apps 1968 KB/s (348794 bytes in 0.173s) 1693 KB/s (553402 bytes in 0.319s) nil
consoleで「start_test_server_in_background」コマンドを実行し、テストサーバーを起動します。
irb(main):002:0> start_test_server_in_background WARNING: linker: libdvm.so has text relocations. This is wasting memory and is a security risk. Please fix. nil
consoleで「exit」コマンドを実行するか、または「Ctrl」+「C」キーを押し、consoleを停止します。
【3】(任意)過去の不要なテストサーバーの削除
アプリのビルド/インストール/テストを繰り返した場合、「{プロジェクトのルート}/test_servers」以下には、過去に使用したテストサーバーのapkファイルが累積して残ります。もし、これらがマシンのディスク容量を圧迫するような場合は、下記コマンドなどで過去の不要なテストサーバー/apkファイルを削除してください。
rm -r ./test_servers
【4】テストシナリオの実行
プロジェクトのルートディレクトリで「calabash-android run {YOUR_APK_FILE}」コマンドを実行します。
$ calabash-android run app/build/outputs/apk/app-calabash-release.apk
ちなみに、テストサーバーを起動せずに「calabash-android run {YOUR_APK_FILE}」コマンドを実行すると、下記エラーが発生します。
HTTPClient::KeepAliveDisconnected (HTTPClient::KeepAliveDisconnected) (RuntimeError)
【5】テストサーバーの停止
プロジェクトのルートディレクトリで「calabash-android console {YOUR_APK_FILE}」コマンドを実行し、consoleを起動します。
$ calabash-android console app/build/outputs/apk/app-calabash-release.apk
consoleで「shutdown_test_server」コマンドを実行し、テストサーバーを停止します。
irb(main):001:0> shutdown_test_server nil
consoleで「exit」コマンドを実行するか、または「Ctrl」+「C」キーを押し、consoleを停止します。
Calabash-Androidを実際に半年以上業務で使用してきた経験から、実際のプロダクト開発でどう対応すべきかについて、筆者なりにアドバイスをさせていただきます。
上記の中でも特に「テスト対象アプリの自動アンインストール/インストール設定の解除」については、すぐにフィードバックサイクルのボトルネックとなりがちです。そのため、この設定解除はプロダクト開発の初期に実施することをオススメします。
一方でテストサーバーの自動起動・停止設定については、以下の理由から、初期状態のまま設定を変更しないことをオススメします。
上記の全て/一部を採用する場合、手動実行だとミスオペレーションの機会が増え非効率にもなりますので、スクリプト化してCIサーバーなどから呼び出せるようにしておくことをオススメします。
リリース用に署名されたアプリについて「calabash-android run {YOUR_APK_FILE}」コマンドおよび「calabash-android console {YOUR_APK_FILE}」コマンドを実行する場合、初回のみkeystoreのパスワードの入力を求められます。
CIサーバーなどからの呼び出しを想定してこれらのコマンド実行をshellなどでスクリプト化する際、このkeystoreのパスワードの指定方法が分からず詰まってしまうことが多いです。
この対処方法の1つとして、次のようにリダイレクトを使う方法があります。
他にも方法はあると思いますが、もし同じ問題につまづいた場合は、まずはこの方法を試してみてください。
Copyright © ITmedia, Inc. All Rights Reserved.