連載
» 2015年06月02日 05時00分 公開

iOS/AndroidのUIテストを自動化するAppiumのテストスクリプトの書き方とインスペクターの使い方スマホ向け無料システムテスト自動化ツール(9)(2/3 ページ)

[外山純生,テスト自動化研究会(STAR)/Androidテスト部]

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」ボタンを押すとアプリが起動します)。右側のペインに調査対象アプリのスクリーンショットが表示されるはずです。

インスペクター画面でサンプルアプリのDetail画面を表示させたところ(Mac OS X版)

 次に、インスペクターに表示されたスクリーンショット上で、調査したいコンポーネントをクリックすると、その部分が赤い枠で囲まれ、中央の「Details」ペインに属性の詳細が表示されます。

属性の詳細を表示させたところ(Mac OS X版)

コラム「インスペクターの赤枠表示機能について」

 スクリーンショット上に、調査対象コンポーネントの位置を赤枠で表示する機能は、まだ実装が安定していないようです。

 筆者の環境では、Mac OS X版では、インスペクターのウィンドウを最大化しないと、スクリーンショットの正しい位置に赤枠が表示されませんでした。また、Windows版では、赤枠自体が表示されませんでした。


 「Details」ペインに表示される属性の中には「xpath」という項目があり、目的のUIコンポーネントを特定するためのXPath表記も確認することができます。

Detailsペインを拡大したもの(Mac OS X版)

 また、画面右下には「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については、この機能を使って意図通り動作するか確認することをお勧めします。

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.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。