今更ながら、Xcode7のUITestを触ってみたのでそれについて書きました。
今後進化していくと思うので、随時書き足していこうと思っています。
参考
http://dev.classmethod.jp/smartphone/iphone/xcode-7-ui-testing/
→簡潔でわかりやすいです
https://www.bignerdranch.com/blog/ui-testing-in-xcode-7-part-1-ui-testing-gotchas/
→細かいところも書いてある
https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/01-introduction.html
→公式だが、UITestについてはあまり書いてない
https://developer.apple.com/videos/play/wwdc2015/406/
→こちらのWWDC2015のPDFに(UITestで利用するクラスについて)詳しく書かれている
必要な環境
- Xcode7以上
- iOS9以上の実機または、Simulator
UITestプロジェクト追加
File -> New -> Target... -> iOSのTest -> iOS UI Testing Bundle を選択して Next -> UITest Targetの設定を必要に応じて変更(多分、普通は変更しない)してFinish。
UITestする操作の記録
下の方のRecord UI Testボタン[赤いボタン]をクリックすると、テスト対象のアプリが起動し、テストするUI操作のコードを記録できる。
- UI操作のコードを記録できるのはお手軽。
- もちろん、コードでも書ける。
- XCUIApplicationインスタンス.buttons[ボタンtext]で、現在表示中の画面から対象ボタンのXCUIElementQueryオブジェクトを取得できて、それに対して何か操作(tapしたり、text取得したり)するような感じ。
UIによって、XCUIApplicationインスタンス.webViews やXCUIApplicationインスタンス.maps など、いろいろ用意されている。
UITest 実行
テストコードを書いて、NavigationBarの<->(右から4番目)クリックして開いて、対象のテストクラスのTest実行。
class XCTestSampleUITests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
XCUIApplication().launch()
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// Use recording to get started writing UI tests.
// Use XCTAssert and related functions to verify your tests produce the correct results.
let expectation = self.expectationWithDescription("test")
let app = XCUIApplication()
//テーブルビューの"2016-03-10 14:32:18 +0000"が表示されているセルをタップ
app.tables.staticTexts["2016-03-22 13:34:34 +0000"].tap()
//starボタンをタップ
app.buttons["star"].tap()
var delay = 1.0 * Double(NSEC_PER_SEC)
var time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue(), {
//label.textに"Twinkle stars!"が表示されているか確認
XCTAssert(app.staticTexts["Twinkle stars!"].exists, "failed to tap star button.")
//loveボタンをタップ
app.buttons["love"].tap()
})
delay = 2.0 * Double(NSEC_PER_SEC)
time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue(), {
//label.textに"Many hearts!"が表示されているか確認
XCTAssert(app.staticTexts["Many hearts!"].exists, "failed to tap love button.")
expectation.fulfill()
})
self.waitForExpectationsWithTimeout(5.0) { (error) -> Void in
if let err = error {
XCTFail(err.description)
}
}
}
上記はテストメソッドがtestExample()の1つだけだが、2つ以上のテストメソッド(メソッド名:test〜のメソッド)がある場合はテストメソッドの数だけ、
Setup(),test〜1つ目のテストメソッド(),tearDown()
Setup(),test〜2つ目のテストメソッド(),tearDown()
・
・
・
のようにTestが実行されていく(これはXCTestの仕様だが)。
バグ(と思われる現象)
- UITestsクラスに2つ以上のテストメソッドがあると、2つ目以降のメソッド実行時のSetup()内のXCUIApplication().launch()で下記のようなエラーが発生。
UI Test Activity:
Assertion Failure: UI Testing Failure - App state for <XCUIApplicationProcess: 0x156e65870 (null) (4528)> is XCApplicationStateRunningActive (3), still not XCApplicationStateNotRunning (1)
→tearDown()でXCUIApplication().terminate()(アプリの終了)をしても解消できない。XCode7.3 beta5ではこの現象は解消されていた。
関連:https://forums.developer.apple.com/thread/28732
- 絵文字のUIだと、Record UI Testボタンでうまく操作記録できない。UI操作用コードが文字化けする。
まとめ
- 便利だがまだ改善の余地がありそう。
- 私自身もっとUITestの理解を深めて記事に追記していこうと思う。