XCUITestがXcode7から利用できるようになったので、少し追ってみたので、メモ。
まだ正式に導入するとか、評価したとか、そういう話ではないです。
以下は、Xcode7.0で適当なXCUITestを書いたあと、コード上でメソッドを追った時の情報をもとに引用しています。Online Documentなどでは違うところがあるかも。また、 Swift をベースに追っています。
accessibility systemを使って要素を特定する
/*! Protocol describing the attributes exposed on user interface elements and available during query matching. These attributes represent data exposed to the Accessibility system. */
どうやら、XCUITestはXCTestを拡張し、さらにはAccessibilityの機構を使うみたいです。ひとまず、UIAutomationのために埋め込んだaccessibilityIdentifeirなど、そのまま流用可能のようです。
ということは、すでにUIAutomationを使いシナリオを記述している人は、テストシナリオを記述する粒度は変われど、同一のシナリオを記述することは可能かもしれないです。
例えば、 public protocol XCUIElementAttributes には
public var identifier: String { get }
が定義されています。これは accessibilityIdentifier の要素を指しているらしいので、accessibilityIdentiiferでつけた要素を特定する、ということは従来のUIAutomationと変わらず実施できます。
この要素特定には、
public func elementBoundByIndex(index: UInt) -> XCUIElement
と
public var allElementsBoundByAccessibilityElement: [XCUIElement] { get }
の2種類が使えそうです。見た感じ。(まだちゃんと使ってはない)
また、accessibilityベースではなく、より実装に依存することになりますが実装対象のUIButtonといったUIKitの要素単位を取得するためのインターフェースとして
public protocol XCUIElementTypeQueryProvider
が宣言されているようです。
ここら辺は、UIAutomationで取得できていた要素を、XCUITestで参照できるようにした、というもののようです。
@available(iOS 9.0, *) のある XCUI* 群
@available(iOS 9.0, *)
のアノテーションで指定されていうr、 XCUI* 群を使うことで、シナリオの記述などを行っていく模様。XCTestのコードを見ていると、随所で @available(iOS 9.0, *) を持った XCUI* 群を確認できます。
ここら辺では、操作を定義してたりしました。ただ、 @available をいろいろ見ていると、iOS7を対象としたものなんかもいろいろあって、XCUITestは今まで用意してきたUIAutomationだったり、accessibilityの要素をまとめあげた感じがしました。
シナリオを書いてみる
少しシナリオを書いてみました。テスト対象は新規でアプリを作成すると作られる、簡単なタスク追加のデモアプリです。その中で、navigation barのEditをタップして、Addする、というシンプルなものを書いてみました。
import XCTest
class SamplesForXCUITestUITests: XCTestCase {
override func setUp() {
super.setUp()
continueAfterFailure = false
XCUIApplication().launch()
}
override func tearDown() {
super.tearDown()
}
func testExample() {
let app = XCUIApplication()
let masterNavigationBar = app.navigationBars["Master"]
masterNavigationBar.buttons["Edit"].tap()
masterNavigationBar.buttons["Add"].tap()
}
}
これで、 cmd + u でXCUITestまでテストが実施されます。アニメーションなんかは従来のUIAutomationと同じ感じで、そのままUIAutomationをXCTestの一部として実施している以上の感想を持ちませんでした。
書いてみて思ったこと。
- XCUITestはUIを見ながらシナリオを考える、というには、いささかテストコードがハードコーティングすぎる
- まだaccessibitliyを付加して、とか試してないので、それによって印象変わるかも
allElementsBoundByAccessibilityElementとかで全要素取得できなかったので、ちょっと全要素取得のコツとか学ばないと、実際に書かれたコードを読む必要性が高い…- ひとまずRuby + Appiumのほうが同様のことをするには良い。実行速度も、Simulator上では、さほど差があるわけではない気がします。(Simulator再起動の時間は除く)
- Espressoみたい
- 特定のViewを直接描画する、とかできるのかな…
- シナリオというか、操作の書き方も…
- 操作のRecordは気軽にできてよいけれど、こういうシナリオの記述に知見がない人だとすぐにスパゲッティ作りそう
- 開発経験を多少持っていると問題ないかな…
感想
Xcodeで accessibility* による補完を見てみると、 UIKit > UIAccessibility の要素も参照していました。ここ、コードを読んでみるとiOS7とか、もっと古くからでも参照できるaccessibilityの要素にたどることができます。今までPrivate APIとして使われていた、FBが出している WebDriverAgent なんかでアクセスしているAPIを整理して、ちゃんとXCUITestのフレームワークとしてアクセスできるようにした、というのが正体なのかもしれませんね。
確かに、UIAutomationの欠点はUI操作をJavaScriptで書かないといけないという、iOS開発者にとってはなかなか酷なものでした。そこをそのままSwiftやObjective-Cで利用出来るように公式でおこなう、というだけでも、有益かもしれません。
KIFは完全にこっちに移りそうな予感がします。FBのWebDriverがこのXCUITestを経由することができるようになれば、AppiumなんかでもXCUITestの恩恵を受けられそう。
いずれにせよ、今までRuby + Appium + Android/iOSとテストを記述していたのですが、”Ruby + Appium + Android” and “XCUITest + iOS” というふうに、iOSにおいては、Ruby(などのほか言語) + Appium を経由してiOSアプリをGUI Testingするといった使い方は制限されそうな予感。次のXcode8とか、そのくらいのタイミングでUIAutomationは除かれる可能性を考えて動いたほうがよさそう。
んー。複数OSのアプリ対応を少人数で動かないといけないとき、UIAutomationが制限される未来に進む場合、iOSは制約厳しいな…