问题
When running an XCT UI test it is possible to put the application under test in the background with:
XCUIDevice().pressButton(XCUIDeviceButton.Home)
It it possible in some way to bring the app back to foreground (active state) without relaunching the application?
回答1:
Update for Xcode 9: Starting in Xcode 9, you can now simply call activate()
on any XCUIApplication.
let myApp = XCUIApplication()
myApp.activate() // bring to foreground
https://developer.apple.com/documentation/xctest/xcuiapplication/2873317-activate
Yes, it is. But, you'll need XCUIElement's private headers (which are available via header dump from Facebook here). In order to foreground the app, you need to call resolve which I believe resolves the element's query (which for applications means foregrounding the app).
For Swift, you'll have to import the XCUIElement.h into your bridging header. For Objective-C you'll just need to import XCUIElement.h.
With the app backgrounded:
Swift:
XCUIApplication().resolve()
Objective-C
[[XCUIApplication new] resolve];
If this is the only functionality you need, you could just write a quick ObjC category.
@interface XCUIElement (Tests)
- (void) resolve;
@end
If you need to launch / resolve another app. Facebook has an example of that here by going through the Springboard.
回答2:
As of Xcode 8.3 and iOS 10.3, you can accomplish this with Siri:
XCUIDevice.shared().press(XCUIDeviceButton.home)
XCUIDevice.shared().siriService.activate(voiceRecognitionText: "Open {appName}")
Include @available(iOS 10.3, *)
at the top of your test suite file and you should be good to go!
回答3:
If somebody needs just move app back from background i have written (based on answer above) category that really works(great thanks to pointing to 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
回答4:
This is what I have in my XCUITest and it works like a charm (xcode 10.1 and test device is iPhone X 11.0)
func testWhatever() {
// You test steps go here until you need the background foreground to run
XCUIDevice.shared.press(XCUIDevice.Button.home) // To background the app XCUIApplication().activate() // To bring the app back
// You test continues after background foreground has been done. }
回答5:
For Swift, you need to declare the XCUIApplication private methods interface in Bridging-Header.h like this:
@interface XCUIApplication (Private)
- (id)initPrivateWithPath:(NSString *)path bundleID:(NSString *)bundleID;
- (void)resolve;
@end
Then call resolve() in your test cases to bring the app back:
XCUIApplication().resolve()
来源:https://stackoverflow.com/questions/35295090/possible-to-bring-the-app-from-background-to-foreground