iOS/AndroidのUIテストを自動化するAppiumのテストスクリプトの書き方とインスペクターの使い方:スマホ向け無料システムテスト自動化ツール(9)(2/3 ページ)
本連載では、AndroidおよびiOSアプリ開発における、システムテストを自動化するツールを紹介していきます。今回は、オープンソースのモバイルテスト自動化ツール「Appium」のテストスクリプトの書き方や、インスペクターの使い方、Appiumサーバーのコマンドラインからテストを実行する方法などについて。
UIコンポーネントの特定から操作までの流れ
次に、サンプルのテストスクリプトを元に、UIコンポーネントの特定から操作までの流れを見てみましょう。
前述のコード例で省略したテストメソッド「新規顧客が追加できること()」の実装は以下の通りです。
@Test public void 新規顧客が追加できること() throws Exception { MasterPage master = new MasterPage(mDriver); DetailPage detail = master.goDetailPageToAddCustomer(); PreviewPage preview = detail.inputName("Yamada Taro") .inputMailAddress("yamada@example.com") .selectGender(Gender.MALE) .inputAge(9) .saveAndPreview(); assertThat(preview.getName(), is("Yamada Taro")); assertThat(preview.getMailAddress(), is("yamada@example.com")); assertThat(preview.getAge(), is("9")); assertThat(preview.getGender(), is("男性")); assertThat(preview.getDivision(), is("C層")); }
4行目で、「MasterPage#goDetailPageToAddCustomer()」メソッドを呼び出していますが、このメソッドは、以下のようなコードで、Master画面の「Add」ボタンをタップ(クリック)しています。
public class MasterPage { // setUp()で生成したAndroidDriverインスタンス protected AndroidDriver mDriver; public MasterPage(AndroidDriver driver) { mDriver = driver; } public DetailPage goDetailPageToAddCustomer() { // Accessibility ID (= AndroidではcontentDescription属性) // が"add"であるUI部品を探し、クリックする。 WebElement addButton = mDriver.findElement(MobileBy.AccessibilityId("add")); addButton.click(); // (省略) } }
ある条件を満たしたUIコンポーネントを取得するには、自動化セッション開始時に生成したAndroidDriverインスタンスの「findElement()」の引数に検索条件を指定します。上記のコード例では「MobileBy.AccessibilityId("add")」が検索条件に当たります。
検索条件の指定方法については後述します。
「findElement()」の戻り値は、検索条件に合致したUIコンポーネント(「WebElement」インターフェース)です。「WebElement」インターフェースに用意されている操作メソッドを呼び出すことで、目的のUIコンポーネントを操作することができます。
上記のコード例では「click()」メソッドを呼び出して、目的のUIコンポーネント(ここでは「Add」ボタン)をクリックしています。
なお、「検索条件」に合致するUIコンポーネントが複数見つかった場合でも、「findElement()」メソッドで取得できるのは1つだけです。見つかった全てのUIコンポーネントを取得したい場合には、複数形の「findElements()」メソッドを利用してください。
UIコンポーネントの特定
「findElement()」の引数に指定する「検索条件」には、「By」クラスや「MobileBy」クラスのstaticメソッドが利用できます。
利用できる主な検索条件は以下の通りです。
- 「By.className()」:UIコンポーネントのクラス名(「android.widget.Button」など)を検索条件に指定する
- 「By.xpath()」:UIコンポーネントのツリー構造をXMLに見立てて、XPathにより検索条件を指定する(後述)
- 「MobileBy.AccessibilityId()」:UIコンポーネントの「contentDescription」属性の値を検索条件に指定する
- 「MobileBy.AndroidUIAutomator()」:uiautomatorの検索条件を文字列で指定する。例えば、「OK」と表示されているUIコンポーネントを検索したい場合には、引数に「"new UiSelector().text(\"OK\")"」と指定する
uiautomatorで検索条件を指定する方法についての詳細は、第2回の記事を参照してください。
インスペクターを使った検索条件の構築
画面上のUIコンポーネントの構成情報を調べることのできるインスペクターが、Appium Desktop Appに搭載されています。特に、Mac OS X版のインスペクターはXPath関連の機能を搭載しているため、XPathで検索条件を指定したいときに大きな力を発揮します。
残念ながら、Windows版のインスペクターはまだ動作が不安定で、実用的といえるレベルにはなっていないため、Mac OS X版のインスペクターについて説明します。
インスペクターを起動するには、Appiumサーバーを停止状態にした後に「Android Settings」ダイアログを出し、以下の項目を設定してください。
- 「Application」→「App Path」にチェックを入れ、調査したいapkファイルの所在をフルパスで指定する
- 「Capabilities」→「Device Name」にチェックを入れ、値は空欄とする
この状態で「Launch」ボタンを押してから、虫眼鏡のアイコンが表示されたボタンを押すとインスペクターが起動します。
同時に、adb接続された端末上で調査対象アプリも起動しますので、調査したい画面を端末に表示させてから、インスペクターの「Refresh」ボタンを押してください(調査対象アプリが自動起動しないこともあります。その場合には、インスペクター起動直後の時点で再度「Refresh」ボタンを押すとアプリが起動します)。右側のペインに調査対象アプリのスクリーンショットが表示されるはずです。
次に、インスペクターに表示されたスクリーンショット上で、調査したいコンポーネントをクリックすると、その部分が赤い枠で囲まれ、中央の「Details」ペインに属性の詳細が表示されます。
コラム「インスペクターの赤枠表示機能について」
スクリーンショット上に、調査対象コンポーネントの位置を赤枠で表示する機能は、まだ実装が安定していないようです。
筆者の環境では、Mac OS X版では、インスペクターのウィンドウを最大化しないと、スクリーンショットの正しい位置に赤枠が表示されませんでした。また、Windows版では、赤枠自体が表示されませんでした。
「Details」ペインに表示される属性の中には「xpath」という項目があり、目的のUIコンポーネントを特定するためのXPath表記も確認することができます。
また、画面右下には「Copy XML」ボタンが配置されています。この「Copy XML」ボタンを押すと、現在表示中の画面上のUIコンポーネント構成情報をXMLで表現したものをクリップボードにコピーできます。
例えば、サンプルアプリのDetail画面にある「男性」ラジオボタンのXMLタグを抜粋すると以下のようになっています。
<android.widget.RadioButton index="0" text="男性" resource-id="com.nowsprinting.hellotesting.appium:id/genderMale" class="android.widget.RadioButton" package="com.nowsprinting.hellotesting.appium" content-desc="" checkable="true" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[164,384][292,443]" instance="0"/>
このように、UIコンポーネントのクラス名が、XPathで検索するときの「要素名」となり、それ以外の「text」や「resource-id」などの項目が「属性」となります(「bounds」属性のように、「Details」ペインの表記と異なる部分がある点に注意してください)。このことを使えばXPath表記をよりシンプルにアレンジできます。
この例ではクラス名が「android.widget.RadioButton」で、「text」属性の値が「男性」ですから、以下のXPath表記でもこのラジオボタンを特定できます。
//android.widget.RadioButton[@text="男性"]
下のペインにある「Locator」タブを選択すると、自分で構築した検索条件が、正しく目的のコンポーネントを探し当てられるか確認できるので、自分で構築したXPathについては、この機能を使って意図通り動作するか確認することをお勧めします。
UIコンポーネントの操作
「UIコンポーネントの特定から操作までの流れ」で少し触れましたが、目的のUIコンポーネントを「WebElement」として取得できれば、「WebElement」インターフェースが提供している以下の操作メソッドを呼び出せます。
- click():目的のUIコンポーネントをクリックする
- sendKeys():目的のUIコンポーネントに対してテキストを入力する
また「TouchAction」クラスを利用することで、ロングタップやドラッグなどの複雑な操作も行えます。詳細はAutomating mobile gesturesを参照してください。
要素の検証
検証したいUIコンポーネントに対応する「WebElement」を取得できれば、そのUIコンポーネントの属性を取得することができます。「WebElement」インターフェースに用意されている、属性値を取得する主なメソッドは以下の通りです。
- getText():text属性の値を取得する
- isEnabled():enabled属性の値を取得する
- isSelected():selected属性の値を取得する
- isDisplayed():画面に表示されているかどうかを取得する
- getAttribute():引数に属性名を指定して呼び出すと、指定した属性の値を取得する。例えば「getAttribute("checked")」はchecked属性の値を取得する
取得した属性値が期待通りであるかを検証することで、テストをパスしたかどうかを判断することになりますが、その具体的な方法は採用したテストフレームワークに依存します。
JUnit 4では、「assertThat()」メソッドがよく使われます。
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、テスト効率化ノウハウ、リモートテストサービスなど