iOS UIテストにおける要素検索のTips

f:id:bamboohero:20210524113733p:plain iOSのUIテストを実装する上で有用な要素検索のTipsをまとめました。

要素検索APIのクラス構成を把握する

UIテストの実装に慣れていないと、要素検索のメソッドチェーンを書こうとするときにどこでどのメソッドを使うのかわからなくなって、APIドキュメントとコードを行ったり来たりしてしまいます。

let element = app.tables.firstMatch.containing(  // あれ、containingがない...?

let element = app.buttons["GreatButton"].matching  // あれ、ここでmatching使えないんだっけ...?

要素検索コードの実装で迷わないようにするには、要素検索APIのクラス構成を把握してしまえば良いのでは?と考えました。

ざっくり以下4つを理解しておけばいいかなと思います。

  • XCUIApplication
  • XCUIElement
  • XCUIElementQuery
  • XCUIElementTypeQueryProvider

f:id:bamboohero:20210428000627p:plain

先の例でいうと、firstMatchはXCUIElementを返すので、matching(:)やcontaining(:)といったメソッドは呼べません。

subscriptはXCUIElementを返すので、同じくmatching(:)やcontaining(:)といったメソッドは呼べません。

各プロパティやメソッドがXCUIElementとXCUIElementQueryのどっちを返すのかを意識すると良いです。

UI構造のスナップショットを見ながら検索コードを書く

UI構造が複雑なアプリでは、実装した検索コードで思うように要素が取得できないことがあります。

要素が取得できるようになるまでコードを修正してはテストを動かして、とやっていると効率が悪いので、LLDBデバッガを活用しましょう。

検索コードの行にブレークポイントを仕込み、UIテストを一時停止させます。

そして、Xcodeのデバッグコンソールでpo appを入力します。すると、UI構造のスナップショットが確認できます。

f:id:bamboohero:20210428003257p:plain

さらに、このコンソールで検索コードを入力し、目的の要素がヒットするか確かめてみましょう。

f:id:bamboohero:20210428003503p:plain

テストコードの実行は停止していますが、アプリの実行は継続しているため、例えば目的の要素が画面に表示されるように手動で調整してから検索コードを試してみるということもできます。

NSPredicateを使った条件検索

要素タイプやaccessibilityIdentifierを使った検索以外に、NSPredicateを使った条件検索が可能です。

例えば、セル内のラベルの文字列にBambooが含まれるセルを検索するコードはこんな感じです。

app.tables.firstMatch.cells.containing(NSPredicate(format: "label CONTAINS 'Bamboo'")).firstMatch

検索条件に指定可能なオブジェクト(この例ではlabel)は、XCUIElementAttributesプロトコルに準拠しているものに限られます。

例えば、labelの他に、titleplaceholderValueといったものがあります。

条件文(この例ではCONTAINS)は他にも色々指定可能です。以下の記事でわかりやすくまとまっていたので参考にしてみてください。

qiita.com

まとめ

要素検索のTipsについてご紹介しました。

今後も便利なTipsが見つかったら追記していこうと思います。