我有一个应用程序,其中页面控件用于指示多个屏幕。当用户点击页面控件(例如:当前所选页面的右侧)时,滚动视图滚动到以下屏幕。效果很好。
我想为这个场景编写一个 UI 测试。我发现我无法点击特定的页面控件“点”来触发该操作。我可以检查的是页面控件是否存在以及当前选定的页面。
另一个问题是,即使我能够这样做,我如何检查滚动视图是否已经滚动?我只能访问滚动视图的框架,而不能访问其边界。
我刚刚开始使用 Xcode UITest,它让我失望。我认为它现在会很强大(它是由 Xcode 7 引入的,之前作为 UI Automation 可用),但似乎还没有。
我将恢复单元测试+手动功能测试。如果有人有其他想法,请分享。
不要这么快放弃,Xcode UITest 有时可能会令人沮丧,但一旦你弄清楚要使用哪些技巧,它们就会非常强大:
您可以像这样测试您的 UIPageControl:
func testPageIndicator() {
let app = XCUIApplication()
app.launch()
let scrollView = app.scrollViews.element(boundBy: 0)
let pageIndicator = app.pageIndicators.element(boundBy: 0)
// test that page indicator is updated when user scrolls to page 2
scrollView.swipeLeft()
XCTAssertEqual(pageIndicator.value as? String, "page 2 of 3")
// test that scrollview scrolls to page 3 when user taps right of the current page in page indicator
pageIndicator.coordinate(withNormalizedOffset: CGVector(dx: 0.9, dy: 0.2)).tap()
XCTAssert(app.otherElements["page_3"].waitForExistence(timeout: 2))
XCTAssertFalse(app.otherElements["page_2"].exists)
XCTAssertEqual(pageIndicator.value as? String, "page 3 of 3")
}
您可以使用
coordinate
方法告诉测试点击 UIElement 的位置。您将 CGVector 对象交给该方法来描述点击位置。
例如,
CGVector(dx: 0.9, dy: 0.2)
告诉测试在元素宽度的 90% 和高度的 20% 处点击元素。
您可以使用它在
UIPageIndicator
中点击当前页面的左侧或右侧(请参阅上面的代码示例)
要测试您是否位于 UIScrollView 中的正确页面上,您可以将每个页面
accessibilityIdentifier
设置为唯一的字符串,然后断言在点击页面控件后具有该标识符的 UIElement 存在。
在我的例子中,页面是 3 个 UIView。我将它们的
accessibilityIdentifier
设置为“page_1”、“page_2”和“page_3”,然后断言“page_3”存在而“page_2”不存在。
这是我用于获取页数和当前页的扩展。它使用正则表达式在字符串
value
中查找两个数字,并假设较大的数字是页数,较小的数字是当前页面。
它的好处是,即使您的设备/模拟器未设置为英语,它也可以工作。
extension XCUIElement {
func currentPageAndNumberOfPages() -> (Int, Int)? {
guard elementType == .pageIndicator, let pageIndicatorValue = value as? String else {
return nil
}
// Extract two numbers. This should be language agnostic.
// Examples: en:"3 of 5", ja:"全15ページ中10ページ目", es:"4 de 10", etc
let regex = try! NSRegularExpression(pattern: "^\\D*(\\d+)\\D+(\\d+)\\D*$", options: [])
let matches = regex.matches(in: pageIndicatorValue, options: [], range: NSRange(location: 0, length: pageIndicatorValue.count))
if matches.isEmpty {
return nil
}
let group1 = matches[0].range(at: 1)
let group2 = matches[0].range(at: 2)
let numberString1 = pageIndicatorValue[Range(group1, in: pageIndicatorValue)!]
let numberString2 = pageIndicatorValue[Range(group2, in: pageIndicatorValue)!]
let number1 = Int(numberString1) ?? 0
let number2 = Int(numberString2) ?? 0
let numberOfPages = max(number1, number2)
var currentPage = min(number1, number2)
// Make it 0 based index
currentPage = currentPage > 0 ? (currentPage - 1) : currentPage
return (currentPage, numberOfPages)
}
/// return current page index (0 based) of an UIPageControl referred by XCUIElement
func currentPage() -> Int? {
return currentPageAndNumberOfPages()?.0 ?? nil
}
/// return number of pages of an UIPageControl referred by XCUIElement
func numberOfPages() -> Int? {
return currentPageAndNumberOfPages()?.1 ?? nil
}
}
你可以这样使用它:
let pageCount = app.pageIndicators.element(boundBy: 0).numberOfPages() ?? 0
for _ in 0 ..< pageCount {
app.pageIndicators.element(boundBy: 0).swipeLeft()
}
UIPageControl
不允许用户点击特定点。根据官方文档
页面控件仅向任一方向前进一页
因此,您可以点击它的右侧部分进入下一页:
let rightOffset = CGVector(dx: 0.75, dy: 0.5)
let rightCoordinate = pageControl.coordinate(withNormalizedOffset: rightOffset)
rightCoordinate.tap()
或者,您可以点击左侧部分转到上一页:
let leftOffset = CGVector(dx: 0.25, dy: 0.5)
let leftCoordinate = pageControl.coordinate(withNormalizedOffset: leftOffset)
leftCoordinate.tap()
或者您可以向左或向右滑动:
pageControl.swipeLeft()
pageControl.swipeRight()