Upgrade to Pro — share decks privately, control downloads, hide ads and more …

生まれ変わったUI Automatorを使いこなす / How to Use Brand New UI Automator Perfectly

TOYAMA Sumio
February 19, 2016

生まれ変わったUI Automatorを使いこなす / How to Use Brand New UI Automator Perfectly

DroidKaigi 2016で発表した、AndroidのテストツールUI Automator 2についての資料です。

発表時のビデオはこちらをご参照ください。

TOYAMA Sumio

February 19, 2016
Tweet

More Decks by TOYAMA Sumio

Other Decks in Programming

Transcript

  1. ⾃⼰紹介 • ⽒名: 外⼭ 純⽣ (TOYAMA Sumio) @sumio_tym (Twitter) / @sumio

    (GitHub) • 所属: NTTソフトウェア株式会社 • 業務内容: 社内Android関連プロジェクトの技術⽀援 • プライベート: •  STAR(テスト⾃動化研究会) •  @IT連載「スマホ向け無料システムテスト⾃動化ツール」 uiautomator/Appiumの回を書きました http://www.atmarkit.co.jp/ait/kw/smapho_testtool.html 2
  2. 話の流れ 1.  概要 2.  基本的な使い⽅ •  準備 •  UI部品の検索と操作 • 

    待ち合わせ 3.  Tips 4.  UI Automator2の使いどころ 5.  まとめ 4
  3. UI Automator2の概要 • Android SDK標準のテストツール http://goo.gl/E5DH9y (developer.android.com) • 特徴 •  ブラックボックステスト向け • 

    複数アプリにまたがったテスト(操作)ができる (ソースやapkが⼿元に無くてもテストできる) • ソースコードリポジトリ https://goo.gl/ONClV1 (android.googlesource.com) ※旧uiautomatorからリポジトリの場所が移動しているので注意 • APIリファレンス http://goo.gl/alp382 (android.googlesource.com) 6
  4. 旧uiautomatorとの違い 旧uiautomator UI Automator2 UI Automator2 対応APIレベル 16以上 18, 19

    21以上 IDE/ビルドツール Eclipse/ant Android Studio/Gradle 実⾏⽅法 uiautomator コマンド Instrumentation Test テキスト⼊⼒ ASCIIのみ Unicode パフォーマンス やや遅い 速い 旧APIの利⽤ ◦ △ ◦ 新APIの利⽤ × △ ◦ 7 おすすめ! 詳しくは https://goo.gl/mTP8ig 参照
  5. 準備: ファイル配置とbuild.gradle 9 EFQFOEFODJFT\   BOESPJE5FTU$PNQJMFDPNBOESPJETVQQPSUUFTUSVOOFS BOESPJE5FTU$PNQJMFDPNBOESPJETVQQPSUUFTUSVMFT  

      BOESPJE5FTU$PNQJMF= DPNBOESPJETVQQPSUUFTUVJBVUPNBUPSVJBVUPNBUPSW  ^ for Instrumentation Test for UI Automator2 •  テストコード格納先 .0%6-&@%*3TSDBOESPJE5FTU •  CVJMEHSBEMF
  6. 準備: 初期化 10 !3VO8JUI "OESPJE+6OJUDMBTT  QVCMJDDMBTT.Z6JBVUPNBUPS5FTU\ !3VMF QVCMJD"DUJWJUZ5FTU3VMFBDUJWJUZ5FTU3VMF 

    QSJWBUF6J%FWJDFVJ%FWJDF  !#FGPSF QVCMJDWPJETFU6Q UISPXT&YDFQUJPO\ VJ%FWJDF6J%FWJDF HFU*OTUBODF *OTUSVNFOUBUJPO3FHJTUSZ HFU*OTUSVNFOUBUJPO  ^  ^ 6J%FWJDFを初期化しておく
  7. UI部品の検索と操作: 基本形 13 VJ%FWJDFGJOE0CKFDU ᫰✝ᦴঽ ៫ਃ •  ᫰✝ᦴঽに合致したUI部品を៫ਃする •  GJOE0CKFDU

    メソッドが2つ •  6J0CKFDUGJOE0CKFDU 6J4FMFDUPS  •  6J0CKFDUGJOE0CKFDU #Z4FMFDUPS  引数・戻り値の型に注⽬!
  8. UI部品の検索と操作: 検索(1/2) 14 •  GJOE0CKFDU メソッドが2つ •  6J0CKFDUGJOE0CKFDU 6J4FMFDUPS 

    •  6J0CKFDUGJOE0CKFDU #Z4FMFDUPS  •  6J4FMFDUPS検索条件の例(旧uiautomator互換) •  #Z4FMFDUPS検索条件の例(UI Automator2 新API) OFX6J4FMFDUPS UFYU 0, DMBTT/BNF #VUUPODMBTT  #ZUFYU 0, DMB[[ #VUUPODMBTT 
  9. UI部品の検索と操作: 検索(2/2) •  6J4FMFDUPS検索条件API •  #Z4FMFDUPS検索条件API 15 メソッド 概要 className(Class)

    Viewのクラス(EditTextやButtonなど)を条件に指定する text(String) Viewの表⽰⽂字列を条件に指定する description(String) ViewのcontentDescription属性値を条件に指定する resourceId(String) ViewのリソースID(⽂字列表現)を条件に指定する メソッド 概要 clazz(Class) Viewのクラス(EditTextやButtonなど)を条件に指定する text(String) Viewの表⽰⽂字列を条件に指定する desc(String) ViewのcontentDescription属性値を条件に指定する res(String) ViewのリソースID(⽂字列表現)を条件に指定する
  10. UI部品の検索と操作: 操作 (6J0CKFDU/6J0CKFDUともに同じメソッド名) 16 メソッド 概要 click() クリックする setText(String) 指定された⽂字列を⼊⼒する

    getText() 設定されている⽂字列を取得する isFocused() フォーカスが当たっているかどうかを取得する
  11. UI部品の検索と操作: 使⽤例 「"OK"ボタン」をクリックする例 17 6J4FMFDUPS6J0CKFDUӼਜҰ࿾൶ 6J0CKFDUPL#VUUPOVJ%FWJDFGJOE0CKFDU OFX6J4FMFDUPS  UFYU 0,

     DMBTT/BNF #VUUPODMBTT  PL#VUUPODMJDL   #Z4FMFDUPS6J0CKFDUӼਜҰ࿾൶ 6J0CKFDUPL#VUUPOVJ%FWJDFGJOE0CKFDU #Z UFYU 0,  DMB[[ #VUUPODMBTT  PL#VUUPODMJDL  
  12. UI部品の検索と操作: 検索タイミング 6J4FMFDUPS6J0CKFDUを使う場合 •  6J0CKFDUの操作メソッドを呼び出したとき ※GJOE0CKFDU 6J4FMFDUPS 呼び出し時ではない •  ⾒付からなかったら6J0CKFDU/PU'PVOE&YDFQUJPO

    •  画⾯レイアウトが変わっても同⼀6J0CKFDU使いまわせる #Z4FMFDUPS6J0CKFDUを使う場合 •  GJOE0CKFDU #Z4FMFDUPS を呼び出したとき •  ⾒付からなかったらOVMMを返す •  画⾯レイアウトが変わると6J0CKFDUは無効になる →4UBMF0CKFDU&YDFQUJPO 18
  13. UI部品の検索と操作: 検索範囲指定 あるUIサブツリーの下だけ 検索する • UiSelector/UiObjectを使う場合: • BySelector/UiObject2を使う場合: 19 6J4FMFDUPSDSJUFSJB ᫰✝ӘゼᾂDIJME4FMFDUPS ᫰✝ᦴঽ

     6J0CKFDUUBSHFUVJ%FWJDFGJOE0CKFDU DSJUFSJB  6J0CKFDUSPPUVJ%FWJDFGJOE0CKFDU ᫰✝Әゼᾂ  6J0CKFDUUBSHFUSPPUGJOE0CKFDU ᫰✝ᦴঽ  ᫰✝Әゼᾂ
  14. UI部品の検索と操作: 検索範囲指定 あるUIサブツリーの下だけ 検索する • UiSelector/UiObjectを使う場合: • BySelector/UiObject2を使う場合: 20 6J4FMFDUPSDSJUFSJBOFX6J4FMFDUPS  SFTPVSDF*E.BUDIFT

     JEMBZPVU  DIJME4FMFDUPS OFX6J4FMFDUPS UFYU 0,  VJ%FWJDFGJOE0CKFDU DSJUFSJB DMJDL  6J0CKFDUSPPUVJ%FWJDFGJOE0CKFDU #Z SFT 1BUUFSODPNQJMF  JEMBZPVU  SPPUGJOE0CKFDU #ZUFYU 0, DMJDL  「layout2」の下にある 「OK」ボタンを押す
  15. UI部品の検索と操作: 検索範囲指定 注意点: 「探索深さ」を指定したいとき 21 6J0CKFDUSPPUVJ%FWJDFGJOE0CKFDU #Z SFT 1BUUFSODPNQJMF 

    JEMBZPVU  SPPUGJOE0CKFDU #ZUFYU 0, EFQUI  DMJDL  「layout1」の直接の⼦供 (探索深さ1限定) の「OK」ボタンを押したい •  UiSelector/UiObjectを使う場合: 不可 •  BySelector/UiObject2を使う場合: EFQUI を使う
  16. UI部品の検索と操作: スクロール スクロールすれば現れる画⾯外の部品操作 22 [Developer options] →[Show touches] をタップしたい 

    6J4DSPMMBCMFMJTU OFX6J4DSPMMBCMF OFX6J4FMFDUPS  DMBTT/BNF -JTU7JFXDMBTT  EFW0QUJPOT-JTUTFU"T7FSUJDBM-JTU    6J0CKFDUTIPX5PVDIFTMJTUHFU$IJME#Z5FYU  OFX6J4FMFDUPS  DMBTT/BNF -JOFBS-BZPVUDMBTT  4IPXUPVDIFT  TIPX5PVDIFTDMJDL  GJOE0CKFDU 使わない 「"Show touches"を⼦孫に持ったLinearLayout」を探す
  17. UI部品の検索と操作: まとめ • ⽬的の似たAPIが2セット存在 •  UiSelector/UiObject (旧uiautomator互換) •  BySelector/UiObject2 (新規追加) • 両者で検索タイミングが微妙に異なる

    •  操作時 vs findObject()時 • 新しいBySelector/UiObject2は細かい部分で改善 •  直接の⼦供の検索 • スクロールサポートは旧APIのみ 24
  18. 待ち合わせ: 概要 • 原則: 操作による画⾯更新を待たずに次に進む •  独⽴した複数のボタン・テキストボックスを 連続操作するときは速くて便利 • 以下のようなケースでは同期(待ち合わせ)が必要 •  直前の操作による画⾯の変化に依存した操作

    •  ボタンを押すとTextViewの表⽰が変わることを確認したい •  テキストボックスに⽂字を⼊⼒し、enabledになった ボタンを押したい •  etc. •  ある操作で画⾯遷移・ダイアログ表⽰が発⽣するとき •  画⾯遷移・ダイアログ表⽰を完了してから次の操作をしたい 26
  19. 待ち合わせ: UiSelector/UiObject 6J0CKFDUの「操作+待ち合わせ」メソッドを呼ぶ 27 メソッド(引数はタイムアウト値) 概要 clickAndWaitForNewWindow(long) クリックしてから、新しい窓 (ダイアログなど)が表⽰されるまで待つ waitForExists(long)

    このViewが表⽰されるまで待つ waitUntilGone(long) このViewが消えるまで待つ ※タイムアウトした場合は、falseが返される ѷ0,ѸՄԧ՛ӼᚭӁӐѬԨԌԊՕԘҶⷭ⒈ҿӶӵӨӑᑻӎ 6J0CKFDUPL#VUUPOVJ%FWJDFGJOE0CKFDU OFX6J4FMFDUPS  UFYU 0,  DMBTT/BNF #VUUPODMBTT  ԨԌԊՕԘҶⷭ⒈ҿӶӵӨӑNTFDᑻӎѭԧԌՈԊԎ԰ᣪәԮԡ԰Ⴃᡇѭ BTTFSU5IBU PL#VUUPODMJDL"OE8BJU'PS/FX8JOEPX - JT USVF  ҽҽҵӳⷭ⒈ҿӶӉԨԌԊՕԘӕሽӃӵ៫ਃӼ⷗Ұ
  20. 待ち合わせ: BySelector/UiObject2 6J0CKFDUの汎⽤的なメソッドを呼ぶ 28 メソッド(引数は条件とタイムアウト値) 概要 clickAndWait(EventCondition, long) クリックしてから、指定された条件が満 たされるまで待つ

    wait(SearchCondition, long) 指定された条件が満たされるまで待つ wait(UiObject2Condition, long) 指定された条件が満たされるまで待つ ※タイムアウトした場合は、null/0/falseが返される 良く使う「条件」は6OUJMクラスに⽤意されている Untilクラスのstaticメソッド 概要 newWindow() 新しい窓(ダイアログ)が表⽰されるまで gone(BySelector) 条件に合致するViewが⾒付からなくなるまで textEquals(String) 表⽰⽂字列が引数で指定された通りになるまで
  21. 待ち合わせ: BySelector/UiObject2 29 ѷ0,ѸՄԧ՛ӼᚭӁӐѬԨԌԊՕԘҶⷭ⒈ҿӶӵӨӑᑻӎ 6J0CKFDUPL#VUUPO VJ%FWJDFGJOE0CKFDU #ZUFYU 0, DMB[[ #VUUPODMBTT

      ԨԌԊՕԘҶⷭ⒈ҿӶӵӨӑNTFDᑻӎ CPPMFBOSFTVMUPL#VUUPODMJDL"OE8BJU 6OUJMOFX8JOEPX  -  ԧԌՈԊԎ԰ӁӉӒҷәԮԡ԰ӼႣᡇҿӅӵ BTTFSU5IBU SFTVMU JT USVF   ҽҽҵӳԨԌԊՕԘӘ៫ਃӔӓӼ⷗Ұ
  22. 待ち合わせ: いつでも使えるもの UiDeviceクラスのメソッドを呼ぶ 30 メソッド(引数はタイムアウト値) 概要 wait(SearchCondition, long) 指定された条件が満たされるまで待つ waitForWindowUpdate(String,

    long) 同⼀画⾯内のUIが更新されるまで待つ ※第1引数はアプリのパッケージ名 performActionAndWait(Runnab le, EventCondition, long) 指定されたアクション(Runnable)を実⾏し、 条件が満たされるまで待つ waitForIdle(long) このアプリがアイドル状態になるまで待つ
  23. 待ち合わせ: 注意 •  OFX8JOEPX系とXJOEPX6QEBUF系の違い ※間違うとタイムアウトするので注意 •  新しい窓(ダイアログ含む)が表⽰されるとき: OFX8JOEPX系 •  同じ窓の中が変化するとき:

    XJOEPX6QEBUF系 •  待ち合わせメソッドの戻り値は必ずBTTFSUする •  タイムアウトしても例外は発⽣しない •  「戻る」キー押下後の待ち合わせには 6J%FWJDFXBJU 4FBSDI$POEJUJPO MPOH  を使う (例)XBJU 6OUJMIBT0CKFDU #ZQLH  UJNFPVU  •  既存"DUJWJUZのSFTVNFは「新しい窓」ではない 31
  24. 待ち合わせ: まとめ •  画⾯の変化を待ってから操作する場合は待ち合わせが必要 •  UiSelector/UiObject: 待ち合わせに使える条件が少ない •  ある程度UiDeviceのメソッドでカバー可能 • 

    BySelector/UiObject2: 待ち合わせ条件を柔軟に指定可能 •  Untilクラスに良く使う待ち合わせ条件がまとまっている •  こまかい注意事項あり •  OFX8JOEPX vs XJOEPX6QEBUF •  待ち合わせの成功確認は⼤事! •  戻るボタン後の画⾯遷移 32
  25. UIの監視: UiWatcher •  6J8BUDIFS: ⽬的のUI部品が⾒つからなかったときに発動するリスナ •  リスナ発動後にUI部品の検索・操作をリトライする。 •  ユースケース: テストを失敗しにくくするのに有効!

    •  ⾊々な画⾯で表⽰されるダイアログを操作する (セッション切れ時のログイン画⾯、レビューお願い画⾯、etc) •  ANR/強制終了ダイアログを閉じてテストを続⾏する •  etc. •  詳細は以下のURLで! ※古い記事ですが考え⽅は同じです •  http://sumio.hatenablog.com/entry/2014/04/06/014941 34
  26. UIの監視: 注意点 • リスナ発動タイミング •  6J0CKFDUの操作メソッド呼び出し時 UI部品が⾒つかるか、タイムアウトするまで、 1秒おきに何回も呼び出される •  GJOE0CKFDU #Z4FMFDUPS

    呼び出し時 UI部品が⾒つからなかったら Window1つにつき1回だけ呼び出される • Espressoとは連携しない •  EspressoのAPI(PO7JFX で⾒付からなかったとき) では発動しない ※混ぜて使うときは注意! 35
  27. タイムアウト値: 定義 • $POGJHVSBUPSクラスに4種類存在 Idle Timeout: アクセシビリティイベントキューのアイドル待ち時間 Selector Timeout: UI部品が⾒えるまでの待ち時間 Action

    Acknowledgment Timeout: UI部品操作が完了するまでの待ち時間 Scroll Acknowledgment Timeout: スクロール操作が完了するまでの待ち時間 36
  28. タイムアウト値: 待つタイミング •  Idle Timeout •  Home/Backキーなど押下直前 (この時間内にアイドル状態にならなければ諦めてキーを押す) •  6J0CKFDUを検索・操作する直前

    (この時間内にアイドル状態にならなければ諦めて検索・操作する) •  Selector Timeout •  6J0CKFDUを検索するとき (この時間内に⾒付からなければ諦める) •  Action Acknowledgment Timeout •  6J0CKFDUを操作するとき (この時間内に操作が完了しなければ諦める) 37
  29. WebViewの操作 •  検索・操作できるような"1*は無い •  6J%FWJDFHFU-BTU5SBWFSTFE5FYU  •  「最後に選択されたテキストを返す」 •  %1BEでフォーカス移動

    Ȕ移動する度にこのメソッドを呼ぶと現在位置がわかる  Ȕ⽬的のテキストに辿りついたら%1BEで操作する •  ⾊々やってみてもOVMMしか返してくれない •  8FC7JFXも操作したい場合はAppiumがおすすめ 詳しくは@ITの記事を参照 •  http://goo.gl/lsw8xf •  http://goo.gl/rUHIb8 39
  30. 使いどころ: Espresso併⽤時の注意点 世界を切り替えるときには待ち合わせを忘れずに &TQSFTTPȒȔ6*"VUPNBUPS 43 㘘⼱ᎅӕԊԗԣԡӃӵӉӫӘՄԧ՛ӼᚭӃ PO7JFX XJUI*E 3JECVUUPO@DPOUBDUT QFSGPSN

    DMJDL   ԹդՇԫԟՏ՛␼⽇ԨԌԊՕԘӼ៫ਃ VJ%FWJDFXBJU 6OUJMGJOE0CKFDU  #ZSFT DPNBOESPJEQBDLBHFJOTUBMMFS  QFSNJTTJPO@BMMPX@CVUUPO  5*.&065@7"-6& DMJDL   ஝Ꮜ㘘⼱ᎅԊԗԣԡՄԧ՛ӼᚭӃ VJ%FWJDFXBJU 6OUJMIBT0CKFDU  #ZSFT 1BUUFSODPNQJMF  JECVUUPO@DPOUBDUT  5*.&065@7"-6&  PO7JFX XJUI*E 3JECVUUPO@DPOUBDUT QFSGPSN DMJDL  UI Automatorで操作したいボタ ンが表⽰されるまで待つ Espressoで操作したい ボタンが表⽰されるまで待つ
  31. まとめ •  UI Automator2について解説しました •  Espressoでテストできない箇所だけUI Automator2の助け を借りると、スモールスタートできます •  6J0CKFDU

    vs 6J0CKFDUの微妙な違いに注意! •  スクロールが必要なところ以外は6J0CKFDUを使っておけば安⼼ •  細かい点で困ったらこの資料を思い出してみてください 45 ご清聴ありがとうごうございました