iOS/AndroidのUIテストを自動化するAppiumのテストスクリプトの書き方とインスペクターの使い方:スマホ向け無料システムテスト自動化ツール(9)(3/3 ページ)
本連載では、AndroidおよびiOSアプリ開発における、システムテストを自動化するツールを紹介していきます。今回は、オープンソースのモバイルテスト自動化ツール「Appium」のテストスクリプトの書き方や、インスペクターの使い方、Appiumサーバーのコマンドラインからテストを実行する方法などについて。
WebViewのテスト
自動化セッションを開始した直後の状態では、WebView内のUIコンポーネントを操作したり、状態を取得したりすることができません。
Appiumでは、UIコンポーネントの特定や検証の対象が「WebViewなのか」「そうでないのか(ネイティブなのか)」をコンテキストとして指定できるようようになっています(Androidの「Context」とは異なりますので、混同しないように注意してください)。
すなわち、WebViewコンテキストを指定すれば、WebView内のUIコンポーネントがその後の操作・検証の対象となり、ネイティブコンテキストを指定すれば、WebViewの外側にあるUIコンポーネントがその後の操作・検証の対象となります。
自動化セッションを開始した直後のコンテキストは「ネイティブ」になっているため、WebViewのテストをしない限り、コンテキストについて気にする必要はありません。テスト対象アプリにWebViewが含まれており、WebView内部に表示されている内容(HTML)を操作・検証したい場合にコンテキストの指定が必要になります。
それぞれのコンテキストは文字列で表現され、「"NATIVE_APP"」が「ネイティブ」を表し、それ以外の文字列が「WebView」を表します。
コンテキストの指定
コンテキストの指定には、自動化セッション開始時に生成したAndroidDriverインスタンスの「context()」メソッドを使います。
また、「getContextHandles()」メソッドで、現在指定することのできるコンテキストの一覧を取得できます。
この2つのメソッドを使うことで、以下のようなコードでWebViewコンテキストに切り替えることが可能です。
例えば、サンプルのテストスクリプトでは、「PreviewPage#ensureWebViewContext()」メソッドで、下記のようにWebViewコンテキストの指定を行っています。
public class PreviewPage { // setUp()で生成したAndroidDriverインスタンス protected AndroidDriver mDriver; // (省略) /** 現在のコンテキストがWebViewコンテキストであるかどうかを判定する。*/ private boolean isInWebViewContext() { String currentContext = mDriver.getContext(); return isWebViewContext(currentContext); } /** * 指定されたコンテキストがWebViewコンテキストであるかどうかを判定する。 * 文字列が"NATIVE_APP"で<b>なければ</b>、WebViewコンテキストであると判断する。 */ private boolean isWebViewContext(String context) { return !context.equals("NATIVE_APP"); } /** * WebViewコンテキストに切り替える。 * すでにWebViewコンテキストの場合は何もしない。 */ private void ensureWebViewContext() { if (isInWebViewContext()) { // すでにWebViewコンテキストの場合は何もしない。 return; } for (String context : mDriver.getContextHandles()) { if (isWebViewContext(context)) { mDriver.context(context); return; } } Assert.fail("WebView context doesn't exist"); } }
UIコンポーネントの特定
WebView内のUIコンポーネントを特定する場合の検索条件について、Appiumのドキュメントには明確な記載はありません。
ただ、WebViewのリモートデバッグ機能がChromeDriverを利用していることから、ChromeDriverがサポートしている範囲(「By」クラスで提供されている範囲)であれば、問題なく動作するはずです。
例えば、サンプルのテストスクリプトでは、「PreviewPage#getMailAddress()」メソッドで、Preview画面(WebViewで実装されています)に表示される顧客のメールアドレスを取得しています。
public String getMailAddress() { ensureWebViewContext(); // WebViewコンテキストにする return mDriver.findElement(By.name("mail")).getText(); }
Preview画面のWebViewで表示されるHTMLは、以下のような形式ですから、上記のコードは、「name」属性が「mail」である要素内のテキストを取得していることになります。
<html> <!-- (省略) --> <body style="background-color:transparent; -webkit-user-select:none;"> <h4 name="name">(ここに顧客氏名が入る)</h4> メール<div name="mail">(ここにメールアドレスが入る)</div></br> 性別<div name="gender">(ここに性別が入る)</div></br> 年齢<div name="age">(ここに年齢が入る)</div></br> 区分<div name="division">(ここにマーケティング区分が入る)</div> </body> </html>
Selendroid modeでの検索条件の指定方法
Selendroid modeでも、UIコンポーネントの特定から操作までの流れはAppium modeと同じですが、利用できる検索条件が、Appium modeとは異なります。
Selendroid modeで利用できる検索条件については、Selendroidの公式ドキュメントを参照してください。
- ネイティブコンテキストの場合:Interacting with Native Elements
- WebViewコンテキストの場合:Hybrid/Web Elements
検索条件の指定方法をAppium modeとSelendroid modeで比較すると、WebViewコンテキストでは両者はほとんど同じですが、ネイティブコンテキストでは「By.className()」以外は全て異なっています。そのため、ネイティブコンテキストでは検索条件の共用は諦めた方が無難です。
サンプルでは、Selendroid mode向けのテストスクリプトを「com.nowsprinting.hellotesting.appiumtest.selendroid」パッケージ配下に配置しています。Appium modeのPage Objectクラスを継承することでAppium modeとの差分のみが分かるようになっていますので、書き方の違いを確認する際の参考にしてください。
端末の回転
自動化セッション開始時に生成した「AndroidDriver」インスタンスの「rotate()」メソッドを呼び出すことで、端末の画面を回転させることができます。
引数に指定できる画面の向きは「ScreenOrientation.LANDSCAPE」と「ScreenOrientation.PORTRAIT」のみです。uiautomatorのような90度単位での回転はできません。
このメソッドを呼び出すと、自動的にセンサーによる画面の自動回転も無効になります。
自動化セッションを終了すると、再度自動回転が有効になるため、後続のテストへの影響を避けるために、tearDown時に必ず「quit()」メソッドを呼ぶようにしてください。
スクリーンショットの撮影
自動化セッション開始時に生成した「AndroidDriver」インスタンスの「getScreenshotAs()」メソッドを呼ぶことで、画面のスクリーンショット(PNG形式)を撮影できます。
メソッドの引数には、撮影したスクリーンショットをどのような形式で受け取るかを指定します。指定できる値は以下の3つです。
- OutputType.BASE64:BASE64形式にエンコードされた文字列
- OutputType.BYTES:バイト配列
- OutputType.File:一時ファイル。テストを実行しているJVMが終了するとファイルも削除される
撮影したスクリーンショットをファイルとして残しておきたい場合は、Apache Commons IOの「FileUtils.writeByteArrayToFile()」を利用して、以下のようにするのが簡単です。
AndroidDriver mDriver; // 自動化セッション開始時に生成したAndroidDriver File f; // スクリーンショットを保存したいファイル名 byte[] screenshot = mDriver.getScreenshotAs(OutputType.BYTES); FileUtils.writeByteArrayToFile(f, screenshot);
なお、本稿執筆時点では、WebViewコンテキストだとスクリーンショットの撮影に失敗します(ChromeDriverのIssue 792)。当面は、ネイティブコンテキストに戻してからスクリーンショットを撮影することで回避してください。
Appiumサーバーのコマンドラインからの実行
Jenkinsなどを使ってCI(継続的インテグレーション)を実現するためには、Appiumサーバーもコマンドラインから実行できる必要があります。現状、Appium Desktop Appに内包されているAppiumサーバーをコマンドラインから実行することはできないため、コマンドライン版を別途セットアップする必要があります。
コマンドライン版のAppiumは、node.jsのパッケージ管理ツールnpmを使ってインストール・実行できます。
Mac OS XでHomebrewを利用しているのであれば、以下のコマンドを実行することでnode.jsとnpmをインストールできます。WindowsやLinuxへのインストール方法についてはInstalling Node.js via package managerを参照してください。
$ brew install node
npmがインストールされれば、以下のコマンドでAppiumサーバーをインストールできます。
$ npm install -g appium
インストールされた「appium」コマンドを実行することで、Appiumサーバーを開始できます。
Appium GUI版の「Android Settings」などで設定できた、Appiumサーバー起動時の設定項目は、コマンドラインオプションで指定します。
例えば、テスト対象のapkファイルのフルパスは、「--app」オプションを使って以下のように指定します。
$ appium --app {プロジェクトのルート}/app/build/outputs/apk/app-appium-debug.apk
指定できるコマンドラインオプションの詳細はServer flagsを参照してください。
次回は、AppiumとTurnipを組み合わせてBDDを実践
今回は、テストスクリプトの書き方を一通り紹介しました。
記事中でも触れましたが、現時点ではUIコンポーネントの特定方法についてのドキュメントが少ないため、本稿の内容がテストスクリプトを書くときの参考になれば幸いです。
次回は「Appium応用編」として、Turnipを組み合わせてBDDを実践する方法について解説します。
- iOS/AndroidのUIテストを自動化するAppiumのテストスクリプトの書き方とインスペクターの使い方
- SeleniumのUIテスト自動化をiOS/AndroidにもたらすAppiumの基礎知識とインストール方法、基本的な使い方
- Calabash-Androidのテスト高速化、GPS、スクショ、データ駆動型テスト
- Calabash-AndroidによるBDDの実践とJenkinsによる「Living documentation」
- Calabash-Androidでテストシナリオを作成する方法
- iOS/AndroidにCucumberのBDDをもたらすテストフレームワークCalabashの基礎知識とインストール
- Androidテストで便利なuiautomatorviewer、UiScrollableの使い方、テキスト入力API制限事項の回避方法
- Android SDK標準の何でもテストツールuiautomatorの基本的な使い方
- システムテスト自動化の基礎知識とMonkeyTalkの使い方
著者紹介
外山 純生
NTTソフトウェア株式会社勤務。数年前よりAndroidアプリケーション開発にかかわり始めたのを切っ掛けに、Androidにおける自動テストに興味を持つようになる。Android関連プロジェクトに対する技術支援業務に携りながら、Android向けのテストツールがもっと広く使われるようになることを願って、ブログにて技術情報を発信中
Blog:sumioの技術メモ
Twitter:@sumio_tym
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- テスト自動化の歴史と今後、良い/悪い事例〜システムテスト自動化カンファレンス2013レポート
テスト自動化を開発の“武器”にするための3つのポイントや、“自動化”の良い事例、悪い事例など、テストの現場を「進化させる」知見が多数紹介されたカンファンレンスの模様をレポートする。 - ビジネス目標を見据えたテスト設計が肝!「DevOps時代のテスト自動化カンファレンス 冬の陣」開催
DevOpsの実践で肝となるソフトウェアテストの自動化。しかし@ITの読者調査でも50%以上が「テスト環境に課題あり」と回答した。これにどう対応すれは良いのだろうか? カンファレンス登壇者の言葉にヒントを探る。 - Kiwi+CocoaPodsで始めるiOSアプリの振る舞いテスト入門
現代の開発現場において欠かせないCI/継続的デリバリを、iOSアプリ開発に適用するためのツールやノウハウを解説する連載。今回は、iOSアプリの機能の振る舞いをテストするテスティングフレームワークの特長とインストールの仕方、主な使い方を解説します。 - Android SDKでビジネスロジックのテストを自動化するには
- 第2回Androidテスト祭りレポート:Android開発の上層テストで失敗しないためのポイントとは
セキュリティ設計や受け入れテストガイドライン、CIツールJenkins+コードレビューGeritt、テスト効率化ノウハウ、リモートテストサービスなど