如何在 iOS Xcode UI 测试用例中启动系统应用

Posted

技术标签:

【中文标题】如何在 iOS Xcode UI 测试用例中启动系统应用【英文标题】:How to launch system apps in an iOS Xcode UI test case 【发布时间】:2016-01-15 21:33:57 【问题描述】:

我有一个应用程序,其主要目的是将数据输入 HealthKit。我想编写一些 Xcode UI 测试来验证它是否成功写入了这些数据,但是我在验证 Health 应用程序中的数据时遇到了一些困难。

当我最初记录我的测试时,它跳过了我模拟的主页按钮按下,但当我滑动到第一个主屏幕并导航到健康应用程序以显示数据点时它正在记录。

我搜索了如何按下主页按钮,发现了这个(有效):

XCUIDevice.shared.press(.home)

但是,它记录的其他调用实际上都不适用于应用程序之外的导航。在主屏幕上滑动的记录代码显然看起来不对,当我将tap()替换为swipeRight()swipeLeft()时也不起作用:

app.childrenMatchingType(.Window).elementBoundByIndex(1).childrenMatchingType(.Other).elementBoundByIndex(1).childrenMatchingType(.Other).element.childrenMatchingType(.Other).element.childrenMatchingType(.Other).elementBoundByIndex(0).childrenMatchingType(.ScrollView).element.tap()

接下来的几行,用于在主屏幕上启动应用程序,甚至不适用于当前可见页面上的应用程序图标:

let elementsQuery = app.scrollViews.otherElements
elementsQuery.icons["Health"].tap()

有什么方法可以实现我正在尝试做的事情,还是我需要等待验证端到端测试,直到我将 HealthKit 读取功能添加到我的应用程序?

【问题讨论】:

【参考方案1】:

Xcode 9

这是使用 Xcode 9 的解决方案

let messageApp = XCUIApplication(bundleIdentifier: "com.apple.MobileSMS")
messageApp.activate()

您可以在this post中找到系统应用程序的捆绑标识符列表

Xcode 8

对于 Xcode 8,它有点复杂 为了从 Springboard 启动应用程序,您需要导入以下标头

https://github.com/facebook/WebDriverAgent/blob/master/PrivateHeaders/XCTest/XCUIElement.h https://github.com/facebook/WebDriverAgent/blob/master/PrivateHeaders/XCTest/XCUIApplication.h

然后使用以下内容(例如使用 Health)

Objective-C

@interface Springboard : NSObject

+ (void)launchHealth;

@end

@implementation Springboard

+ (void)launchHealth

    XCUIApplication *springboard = [[XCUIApplication alloc] initPrivateWithPath:nil bundleID:@"com.apple.springboard"];
    [springboard resolve];

    XCUIElement *icon = springboard.icons[@"Health"];

    if (icon.exists) 
        [icon tap];

        // To query elements in the Health app
        XCUIApplication *health = [[XCUIApplication alloc] initPrivateWithPath:nil bundleID:@"com.apple.Health"];
    


@end

斯威夫特

class Springboard 
    static let springboard = XCUIApplication(privateWithPath: nil, bundleID: "com.apple.springboard")

    class func launchHealth() 

        springboard.resolve()

        let icon = springboard.icons["Health"]
        if icon.exists 
            icon.tap()

            // To query elements in the Health app
            let health = XCUIApplication(privateWithPath: nil, bundleID: "com.apple.Health")
        
    

【讨论】:

【参考方案2】:

斯威夫特 4

let app = XCUIApplication(bundleIdentifier: "com.apple.springboard")

【讨论】:

【参考方案3】:

您将 UI 测试与您的应用程序绑定在一起,当您按下主页按钮并移出应用程序 UI 时,您无法执行 UI 操作,因为代码中的 app 变量指向您的应用程序。

你可能有类似的代码

let app = XCUIApplication()

所以你应该修改 XCUIApplication() 行。

let app = XCUIApplication(privateWithPath: nil, bundleID: "com.apple.springboard")

现在您可以退出应用程序了。

据我所知,最好拥有独立的 UITestAgent 应用程序并使用跳板捆绑 ID 启动其 UiTestcases,这样您就可以在该应用程序的帮助下测试任何应用程序,而不是像我在产品 XYZ 代码库中编写一些测试用例一样下一个产品 ABC 我将在 ABC 产品的代码库中编写测试!

【讨论】:

以上是关于如何在 iOS Xcode UI 测试用例中启动系统应用的主要内容,如果未能解决你的问题,请参考以下文章

iOS自动化之启动多个WDA

iOS自动化之启动多个WDA

xcode 8 执行 UI 测试用例有啥命令吗?

如何从 XCTest 中的 UI 目标调用主目标中的方法?

如何在 Xcode 中运行单个 UI 测试

如何在 Xcode 中为 Apple Watch 添加单元测试?