能否将应用程序从后台调至前台?

16

运行XCT UI测试时,可以通过以下方式将被测试的应用程序置于后台:

XCUIDevice().pressButton(XCUIDeviceButton.Home)

有没有办法将应用程序重新置于前台(活动状态)而无需重新启动应用程序?


1
Swift 5 语法:XCUIDevice.shared.press(XCUIDevice.Button.home) - Syed Asad Ali
6个回答

12

Xcode 9更新:从Xcode 9开始,你可以在任何XCUIApplication上直接调用activate()

let myApp = XCUIApplication()
myApp.activate() // bring to foreground

https://developer.apple.com/documentation/xctest/xcuiapplication/2873317-activate


是的,确实需要。但是,您需要 XCUIElement 的私有头文件(可通过从 Facebook 此处 获得头文件转储)。为了将应用程序置于前台,您需要调用 resolve,我相信这会解析元素的查询(对于应用程序而言,这意味着将应用程序置于前台)。

对于 Swift,您需要将 XCUIElement.h 导入到桥接头文件中。 对于 Objective-C,您只需要导入 XCUIElement.h。

将应用程序置于后台:

Swift:

XCUIApplication().resolve()

Objective-C

[[XCUIApplication new] resolve];

如果这是您所需的唯一功能,那么您可以编写一个快速的ObjC类别。

@interface XCUIElement (Tests)
- (void) resolve;
@end
如果您需要启动/解决另一个应用程序。Facebook通过Springboard的方式提供了一个示例。

我相信这种方法也可以奏效,但是相比于使用XCUIApplication().launch(),它需要更多的绕路。 - skim
这个对你们还管用吗?我感觉@brandenbyers的解决方案可能更好。 - gran_profaci
你如何完成这一部分?:你需要将XCUIElement.h导入到你的桥接头文件中。 - reutsey
是的,我知道需要这样做,但具体怎么做呢?抱歉,我不熟悉在哪里找到桥接头,或者我需要放什么。如果您能让我知道或添加到上面,那将非常棒!谢谢。 - reutsey
如果您将任何Objective-C类文件添加到测试目标(通过文件->新建文件,而不是拖入),Xcode将为您提供自动创建桥接头文件的选项。只需用XCUIElement接口替换所创建文件的内容即可。 - Chase Holland
显示剩余4条评论

5

从Xcode 8.3和iOS 10.3开始,您可以通过Siri实现此功能:

XCUIDevice.shared().press(XCUIDeviceButton.home)
XCUIDevice.shared().siriService.activate(voiceRecognitionText: "Open {appName}")

在测试套件文件的顶部包含@available(iOS 10.3, *),然后您就可以开始了!


需要注意的是,在iOS模拟器上使其工作,您需要在设置应用程序中启用Siri(默认情况下关闭)。不幸的是,我不确定是否有通过命令行参数或其他方式打开它的方法。 - Mark Feaver
好的观点。无论是物理设备还是模拟器,都必须启用Siri才能使其正常工作。幸运的是,每个模拟设备只需要启用一次Siri即可。根据我的经验,该设置在模拟器重新启动之间保持不变。我还没有找到通过命令行启用模拟器上的Siri的方法。 - brandenbyers

3

以下是我在我的XCUITest中使用的代码,它可以完美运行(xcode 10.1和测试设备为iPhone X 11.0)

func testWhatever() {

// 在此处添加测试步骤,直到需要在后台前台运行

XCUIDevice.shared.press(XCUIDevice.Button.home) // 将应用程序放入后台 XCUIApplication().activate() // 将应用程序带回前台

// 在完成后台前台操作后,继续执行测试。 }


1
如果有人只是需要将应用程序从后台移回,我已经写了一个(基于上面的答案)类别,真的很有效(非常感谢指向FB git)。
@implementation XCUIApplication(SpringBoard)

+ (instancetype)springBoard
{
    XCUIApplication * springboard  = [[XCUIApplication alloc] performSelector:@selector(initPrivateWithPath:bundleID:)
                                                                   withObject:nil
                                                                   withObject:@"com.apple.springboard"];




    [springboard performSelector:@selector(resolve) ];
    return springboard;
}

- (void)tapApplicationWithIdentifier:(NSString *)identifier
{
    XCUIElement *appElement = [[self descendantsMatchingType:XCUIElementTypeAny]
                           elementMatchingPredicate:[NSPredicate predicateWithFormat:@"identifier = %@", identifier]
                           ];
    [appElement tap];
}
@end

0

自从 Xcode 13 后,我们遇到了几个错误,即在返回应用程序后应用程序未处于前台状态。

将此代码应用于我们的“goToSpringboardAndBack()”可正常工作。

XCUIDevice.shared.press(XCUIDevice.Button.home)
if XCUIApplication().wait(for: .runningBackground, timeout: 5.0) {
   XCUIApplication().activate()
}

_ = XCUIApplication().wait(for: .runningForeground, timeout: 5.0)
´´´

0
对于 Swift,您需要在 Bridging-Header.h 中声明 XCUIApplication 私有方法接口,例如:
@interface XCUIApplication (Private)
- (id)initPrivateWithPath:(NSString *)path bundleID:(NSString *)bundleID;
- (void)resolve;
@end

然后在您的测试用例中调用resolve()将应用程序恢复:

XCUIApplication().resolve()

你在哪里找到 Bridging-Header.h 文件? - reutsey
1
当您将一个 objc 文件添加到 Swift 目标时,它会自动创建。如果您还没有这样的文件,最简单的方法是创建一个空的 objc 文件并将其添加到目标中。Xcode 会询问您是否需要桥接头文件 - 选择是。然后删除您创建的空的 objc 文件,桥接头文件将保留。否则,您可以创建一个头文件并在“项目->构建设置->Objective-C 桥接头”中设置其路径。 - Chase Holland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接