How to perform UITesting on an app I don't have source code for? - ios

I have been reading up on Apple's new and improved XCTest/UITesting frameworks and I have some questions as a Android developer. In android, to launch an app that I do not have the source code for to run UiAutomator I would simply use
#Before
public void setup() {
//Init UiDevice instance
Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
mDevice = UiDevice.getInstance(mInstrumentation);
//start from home screen on each new test
mDevice.pressHome();
//wait for launcher
final String launcherPackage = mDevice.getLauncherPackageName();
assertThat(launcherPackage, notNullValue());
mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);
//launch app
Context mContext = InstrumentationRegistry.getContext();
final Intent intent = mContext.getPackageManager()
.getLaunchIntentForPackage(GMAIL_APP_PACKAGE);
//Clear any previous instances
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
mContext.startActivity(intent);
//wait for app to appear
mDevice.wait(Until.hasObject(By.pkg(GMAIL_APP_PACKAGE).depth(0)), LAUNCH_TIMEOUT);
mDevice.waitForWindowUpdate(null, 5000);
}
Using the above code, i am able to launch the package i want then use UiAutomatorView.bat to inspect the elements and get their resource id's (or find by text) then perform operations on them.
In iOS, all of the tutorials that i've found centre on testing apps that you have access to source code for. While I understand that it is much simpler to write these tests in iOS since you simply record the actions you wish to perform and xcode writes the code for you, I am unsure as to how to set the UI Test Target to an app that is currently installed on my device. I watched the WWDC video that went over multi-app testing using this:
var gmailApp: XCUIApplication!
gmailApp.launchArguments = "-StartFromCleanState", "YES"]
gmailApp.launch()
however this will not work since it has no target.
TL;DR: How do I set an app installed on my device, such as gmail, as my UI Test Target, and how do i discover package names in order to launch the app?
Thanks!

I don't believe this is possible unfortunately.

You only need the bundle identifier to launch another application.
https://developer.apple.com/documentation/xctest/xcuiapplication/2879415-initwithbundleidentifier?language=objc
I use this for macOS testing a lot so I guess it will work for iOS as well.

Related

Intent does not appear in Supported Intents

Link to all the code I'm working with so far: https://github.com/banool/respose.
I want to make an app where it is possible for users to activate some intent it defines as an action in response to some event in the iOS shortcuts app. For example:
If I open app X.
Run intent from my app instead.
I've seen this done before in other apps, so I know it's possible.
I have an intent defined (see attached code as well as image) that seems to be correct as far as I can tell. I don't think I need an intent extension because I don't intend to handle the intent in the background or via Siri.
I notice that when I try to add an intent under My Target -> General -> Supported Intents, the dropdown doesn't show my intent, only the built in system intents.
I'm not sure what I'm doing wrong here. I got to this point just by following the official guide from Apple: https://developer.apple.com/documentation/sirikit/adding_user_interactivity_with_siri_shortcuts_and_the_shortcuts_app.
I don't think the fact that I'm using Flutter should matter so much right now (I figure that's more of a concern for when the app actually opens up from the shortcut), but perhaps I'm wrong.
I have registered the app on App Store connect and I'm using an identifier that has the sirikit capability enabled. I've also added the "Siri" capability in XCode. I've tried this on both a simulator and a real device, the results are the same.
Any help would be much appreciated, thanks!
Had the same issue.
It seems that you can just type the class name without prompt, and it should work just fine. Don't forget to select proper target though

mozilla webxr-viewer remote debug on non-jailbroken ios

webxr viewer is an webxr-enabled browser for ios.
works great so far, but now i am at a point where i need to debug my scenes.
i can connect the phone to a mac and debug safari,
is there a way to get that same functionality for the webxr-viewer app?
the viewer itself has a "webxr debug" button, so i guess the developers thought about this possibility, but no documentation ever mentions how to actually connect to a debug ui/app on the mac.
am i right in assuming i would have to download the webxr branch from the firefox-ios github and build it myself?
is there a way to debug arkit directly?
theoretically, one could do as i write above,
clone the webxr branch of firefox-ios, then build it in xcode and install it via usb on the phone.
i started doing so, until i clicked the build button:
this needs a developer account with apple to work.
since i do not know if building firefox-ios would allow me to debug the arkit scene, i decided not to bother.
i instead opted to solving this using a classical ie6-style debugDiv:
const debugDiv = document.createElement('div')
document.body.appendChild(debugDiv)
try {
// ... code that errors
} catch(e) {
debugDiv.innerHTML += e.toString()
}
this needs to be done inside the arkit executed code, since arkit adds a weird sandbox, also requires the "dom-overlay" feature in webxr to be requested and available, but if those two prerequisites are met, it works like it's 2001...

How does a UI app inspectors (like the one in Appium) work?

Appium has a way to inspect the view hierarchy of an app using an inspector. I am interested in building one myself.
I know the overview answer of: it uses some webdriver to accomplish this. But how?
It puzzles me that a separate iOS app can some how communicate to another app, and show even its screen.
How does it work under the hood? or how does the iOS app communicate to the UI inspector to send its screen shots and hierarchy?
It puzzles me that a separate iOS app can some how communicate to another app, and show even its screen.
Yes! Apps should not be able to do this. But there exists a special kind of app, built just for testing, which IS able to do this.
The way this is done is using Apple's XCUITest framework. When you write an XCUITest in XCode, it builds a special app which is able to start your test app and then communicate with it using the XCUITest methods. These methods allow you to inspect elements in the view.
In order to create a view tree, you start at the root view and iterate over the children, building out a tree with a tree traversal.
Normally, the XCUITest app exits when your test script finishes, which means you won't be able to access it from a desktop app for viewing the tree as it updates. If you write your test script to run an infinite loop and open a network port for communication with an outside process, now you can build your viewer. This is exactly what Appium does, so I suggest you check out the appium source code and maybe just use that?
More information in this blog post
[edit]: Oh yeah, Appium uses Feacebook's WebDriverAgent project as the script that runs on the app. So WebDriverAgent is basically an XCUITest script which runs a server and can take commands during a test. Appium does a ton of work to bundle and package it into the special kind of companion app that is able to access your app, installs it on the iOS device, and then runs the test. WebDriverAgent has a command which iterates over the UIHierarchy and returns the whole tree.

GCKDiscoveryManager not founding Chromecast devices iOS SDK

I'm trying to find Chromecast devices with my iOS App.
I've downloaded cast SDK via CocoaPods, and then I try the following:
let gckCastOptions = GCKCastOptions(receiverApplicationID: kGoogleCastAppReceiverId)
GCKCastContext.setSharedInstanceWithOptions(gckCastOptions)
GCKLogger.sharedInstance().delegate = self
self.discoveryManager = GCKCastContext.sharedInstance().discoveryManager
self.discoveryManager!.addListener(self)
self.discoveryManager!.passiveScan = true
self.discoveryManager!.startDiscovery()
And then, in the listener method:
func didStartDiscoveryForDeviceCategory(deviceCategory: String) {
print("GCKDiscoveryManagerListener: \(deviceCategory)")
print("FOUND: \(self.discoveryManager!.hasDiscoveredDevices)")
}
Result is always false :(
On my Mac, when I open YouTube, I can stream video to Chromecast device, so device is set definitely.
I am testing on simulator? Should I try it on real device? I suppose that this is not necessary since I'm only trying to discover the available devices.
I've tried to add GCKDeviceScanner too, no luck. I suppose that this is the starting point.
Tried to add GCKUICastButton via storyboard - not being able to do it :(
Have a look to this setting. As soon as I enabled it it started working
Also, please make sure you set another kReceiverAppID other than the given example (AABBCCDD), for example we are using the one listed on the example app, for example static NSString *const kReceiverAppID = #"4F8B3483" (I guess you need to make your own at Google Play Developer Console)
And finally, you can be pretty sure it will never work on a simulator, you need REAL device for this.
Have a look in this setting. Go to project capabilities
Go to project setting and select device capabilities. select this option as discussed in image

Role of framework in between Extension and App in ios

I'm bit confused about the concepts of Extension in ios. After going through some tutorials I still have doubt how an app and an extension in ios communicate each other, does this has to do anything with Framework. If Yes, why we are adding Frameworks...
Hoping for a response, Thanks
App extensions are not stand alone apps. They are providing extended functionality of the app (which can be accessed from main app, called the host app) that is meant to be efficient and focused towards a single task.
For example, Today widget in iPhone is an extension. We can create a today widget for an iOS app which is an extension of the existing iOS app. For example, let us consider an app which shows current weather in detail. Then you can create an extension for this app, to show only current temperature without much detail in a widget.
The extension uses the data which is shared between both the main app and the extension. Embedded framework is a technique to share same code between two targets. You can share data using NSUserdefaults and app group concept.

Resources