在 XCUITest 裡處理畫面捲動,直到目標元件出現

使用 XCUITest 基本上我們不需要自己處理畫面捲動的問題,例如要點擊某個按鈕,但該按鈕需要捲動畫面直到按鈕顯示後,才能點擊到此按鈕,但其實 XCUITest 只要抓到該元件後,直接點擊該按鈕就會自動捲到此按鈕出現,但有些情況下可能無法這麼順利操作 (可參考此篇官方說明),此時我們就需要自己來處理畫面捲動的操作。

本篇文章將帶大家透過 XCUITest 實作捲動畫面至某個元件出現後就停止捲動。(使用開發環境 Xcode 7.3.1)

例如有一個 TableView 如下圖所示,我們要捲動至第 13 個 Cell 上後,接著再對 UI 驗證或操作。

xc1

在 Stack Overflow 你可能會找到此篇教學,提供的做法如下所示:

首先我們必須擴展原本 XCUIElement,先加入 visible() 這個函示判斷元件是否顯示在畫面上,如果元件已顯示在畫面上則此函示會回傳 true,反之則回傳 false,接著加入 scrollToElement() 函示,可以看到這個函示的實作會一直呼叫 swipeUp() 函示將畫面往上捲動,直到指定的元件出現後就停止捲動。

extension XCUIElement {
	func scrollToElement(element: XCUIElement) {
		while !element.visible() {
			swipeUp()
		}
	}

	func visible() -> Bool {
		guard self.exists && !CGRectIsEmpty(self.frame) else {
			return false
		}

		return CGRectContainsRect(XCUIApplication().windows.elementBoundByIndex(0).frame, self.frame)
	}
}

 

Test Code 如下所示:

func testScrollTable() {
	let app = XCUIApplication()
	let table = app.tables.elementBoundByIndex(0)
	let cell12 = table.cells.elementBoundByIndex(12)
	table.scrollToElement(cell12)
}

 

雖然這做法可能就能處理大部分的情況,不過此做法是使用 XCUITest 裡面本身提供的 swipeUp() 函示來捲動畫面,但這個捲動畫面的位移大小我們並無法控制,如果畫面轉成橫向,呼叫 swipeUp() 一次就會捲動過大,可能導致要捲至的元件早就捲過頭,而程式還一直捲動畫面,如下圖所示:

xcui_1

 

因此必須控制一次要捲動的位移大小,來解決過度捲動的問題,我們可透過設定從某個起始點,點選後再拖動至某個終點,這樣就可以根據不同的需求來客製化要如何捲動,如下圖所示,我們可以知道畫面的原點在左上角,橫向為 X 軸,縱向為 Y 軸。

xc2

有了以上的觀念後,我們就可以根據畫面的座標位置,來設定要拖動的起點與終點,稍微改一下原本的做法,完成後程式碼如下所示:

extension XCUIElement {
	func scrollToElement(element: XCUIElement, scroll:() -> Void) {
		while !element.visible() {
			scroll()
		}
	}

	func visible() -> Bool {
		guard self.exists && !CGRectIsEmpty(self.frame) else {
			return false
		}

		return CGRectIntersectsRect(XCUIApplication().windows.elementBoundByIndex(0).frame, self.frame)
	}
}

 

Test Code 如下所示:

func testScrollTable() {
	let app = XCUIApplication()
	let table = app.tables.elementBoundByIndex(0)
	let cell12 = table.cells.elementBoundByIndex(12)
	let mainWindow = XCUIApplication().windows.elementBoundByIndex(0)

	mainWindow.scrollToElement(cell20) {
		let fromPoint: XCUICoordinate = mainWindow.coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: 0.75))
		let toPoint: XCUICoordinate = mainWindow.coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: 0.25))

		fromPoint.pressForDuration(0, thenDragToCoordinate: toPoint)
	}
}

 

我們將原本使用 XCUITest 提供的 swipeUp() 改用自己客制的 scroll(),這個客製化捲動是使用閉包(Closures)來實作,這樣使用者就可容易地根據不同需求來調整操作。

可以看到以上程式碼,我們會先抓到整個畫面 (window),且指定變數名稱為 mainWindow,接著從 mainWindow 整個畫面中來設定 fromPoint 座標,再拖拉到指定的 toPoint 座標來捲動畫面,而這裡 fromPoint 跟 toPoint 都是透過 Normalized Offset 來抓座標位置,也就是按照百分比位置,舉例來說如果 mainWindow 大小為 500 (High) * 300 (Width),則 fromPoint 會抓到 (150, 375) 而 toPoint 為 (150, 125) ,這樣就可以指定要捲動的位移大小。

經過調整後,我們就可以控制捲動的位移大小,因而解決原本方法會造成過度捲動的問題,如下圖所示:

xcui_2

 

畫面捲動位移的大小須根據不同的需求來選擇適合的方法,本篇教學提供一個可以讓使用者控制要捲動的幅度,希望對大家在處理畫面捲動的問題有所幫助。

 

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s