I want to automate the Robotium tests running on my Android application, however, I need to pass in parameters to my tests in order to allow them to run with that configuration.
I can start my tests from the command line as such:
adb shell am instrument -r -w -e PARAM PARAM_1,PARAM_2 com.company.product.application.test/android.support.test.runner.AndroidJUnitRunner
I grab these parameters as such in my code:
Bundle extras = InstrumentationRegistry.getArguments();
if (extras.containsKey("PARAM")) {
this.param1= new ArrayList<>();
this.param1= Arrays.asList(extras.getString("PARAM").split("\\s*,\\s*"));
}
I am intending to call the Device Farm API (https://docs.aws.amazon.com/devicefarm/latest/APIReference/Welcome.html) to run the tests, but I am struggling to find anywhere where I can declare my arguments/parameters. Or find a way of uploading them in a file somewhere in AWS for the Device farm to read from.
I have found some articles from 4-5 years ago claiming that passing launcher parameters was not supported but it was being looked into, in case some claim me lazy, but no one has responded to any questions there, or on the Amazon forums so I thought I would place the question here.
Can anyone help me with the above?
The tests are executed by Device Farm internally so there's no way to control the arguments that get sent to it when running, currently. However, it should be possible to include additional files which could hold that same info for the tests. Here are two ideas I have regarding this:
The tests could use the extra data feature of Device Farm. The extra data zip file gets uploaded to the /sdcard on the device. Then the tests could get the information from the device itself. This is part of the schedule run API so the script running the tests can do this programmatically.
There could be a file that's included in the test apk that's uploaded to Device Farm. I've done something similar with Java Appium tests but not with instumention. In theory it should work.
Other than that, I have not found other ways of including arguments or files for Device Farm.
Hth
-James
Related
I have a problem that I think is related with Android permissions, however I need some of your expertise to confirm it.
I have testing the old Samgung J5(Not rooted) with Android 8.1.0, Appium 1.10.0 with UiAutomator2 and ADB 10.0.40 (In administration mode) on some Call Handling scenarios where I need to check if determined display elements (identity, call duration, hold activated, on transfer information, etc) are displayed to user. I have seen multiple solutions to do this task, inclusively using adb to do it, but lets focus only on this problem, using only the display elements (GUI).
Scenario, user receives call.
The com.android.incallui.service.SecCallPopupService comes into action:
User receives call
When I try to inspect the com.android.incallui.service.SecCallPopupService window the Appium cannot found it:
Appium Inpector
Neither on UiAutomatorViewer:
UitAutomatorViewer
On Comment link (xml dump) you can seen the display elements that Appium, and UiAutomatorViewer can "see". Same result was obtained by using the command adb shell uiautomator dump /data/local/tmp/uidump.xml
After that, I installed the Appium Studio and try out the Appium official "Inspector" and the result was:
Appium Studio Object Spy with full access to all display elements. Very intriguim... after some research I found the following package com.experitest.uiautomator.test (running in background) was immediatelly installed on the device when I clicked on Object Spy feature and I think that is responsible to retrieve all the interface elements.
On comment link (logcat) Some logcat logs after doind object spy on Appium Studio:
Analysing the logcat we can see that Appium studios was requesting
{"response":"true","params":[],"command":"richDump"} and the package uses
some kind of node:android.view.accessibility.AccessibilityNode. Maybe using something like the Acessibility Tree node to get the elements ? I don't know...
I have read some similar questions on Stackoverflow but some solutions involves to root the device or using de ADB (its not an option),
Tryng to su root the device and chmod 777 /data/local/tmp, but if it's really necessary, how then Appium Studio can read all display elements?
Do you know any other solution that allows me to get all interface elements without root the device? How can I call the "richDump"?
Thank You for you help.
So I have a python script to test an android app with the monkeyrunner tool and at a certain point in the script, I have command to launch the application on the mobile phone. The command is: device.shell('monkey -p com.blah.blah -v 500') and it works perfect. But my question is: "What is the meaning of the number 500?"
I found this command on a forum and some users are using the value 300 instead of 500 or other values.. For me it works with all of them but not without it. I just need to understand what the number does so I can fully understand what I do.
As per Android Documentation this command will launch your application and send 500/300/200(as specified by you) pseudo-random events to it such as clicks, touches, or gestures.
I am developing a QA automation solution that can record/playback QA tests on Android. A key business requirement is to have no dependency on a connected PC while playing back the recorded test. To that end, I'm trying to run an Instrumentation test without a connected PC. (Specifically, an Appium UiAutomator2 test).
My current approach is trying to run the test programmatically from my app. If I were running the test normally from a connected PC, I would use the command adb shell am instrument -w. I tried accessing ADB Shell from my app and running am instrument -w, but this produces an error that I am missing the INTERACT_ACROSS_USERS_FULL permission.
To get around this issue, I am trying to run the test using startInstrumentation. This successfully starts the test. However, the test immediately crashes. Upon further investigation, I traced the crash to an NPE: the test is trying to retrieve InstrumentationRegistry.getInstrumentation.getUiAutomation(0), but this returns null.
How do I run the test programatically and give it access to the required UiAutomation instance?
This is how I start the test:
public void runTest() {
final String pm = getPackageName().replaceFirst(".test$", "");
final InstrumentationInfo info = getInstrumentationInfo(pm);
if (info != null) {
final ComponentName cn = new ComponentName(info.packageName,
info.name);
Bundle arguments = new Bundle();
arguments.putString("class", "io.testim.appiumwrapper.test.AppiumUiAutomator2Server");
//cn = {io.extension.test/android.support.test.runner.AndroidJUnitRunner}
startInstrumentation(cn, null, arguments);
}
}
see signature protection level - clarifying ...unless having the package white-listed by Google's release key, you won't be able to obtain the necessary permission. this is a security/integrity feature, with the purpose to limit what malware is able to do - and what you intend to do there, is typical malware behavior - no matter the actual intention of it; working against the system leads nowhere.
the only way I could imaging would be to run commands directly from a terminal emulator or the test application - against a custom build of AOSP, so that you could add android:protectionLevel="signature" to the Manifest.xml and then require android.permission.INTERACT_ACROSS_USERS_FULL. but with a stock ROM, there definitely is no chance to do so. it is not, that it would be "impossible", but building a custom ROM means quite some effort, in order to get there. at least for Nexus and Pixel devices, the required drivers are available here; for other devices, you'd have to find them at the device's vendor, if they're even available.
the trick is to sign off the ROM with the same key as the app - only then signature level permissions can be obtained - while for a stock ROM, you'd (theoretically) need Google's release key to sign off the package. one can enforce single user, as explained here, while this also is only available to system apps.
At work, we have an Android-based infotainment system that we're constantly deploying new versions to, on a half-dozen different test benches. The deployment script does the moral equivalent of:
for apk in ${apk_files}; do
adb install -r ${apk]
done
After this, we need to manually execute the following steps:
Set the home app to be one of our just-installed applications (Always, not Just Once)
Become a developer, and enable the Stay Awake option
Select the Google TTS engine for text-to-speech functionality rather than Pico
Executing these steps after each deploy is a giant PITA. People often forget one or more steps, and leave the test bench in a non-working state. This results in a bunch of 'bogus' bug reports that waste everbody's time.
Is there some way (using adb, perhaps) that we can automate these steps?
You can disable other home apps with adb shell pm disable .... I don't think there's a command line option to set apps as default. I remember looking into this before and there was a "preferred application" XML file where this was stored. If you want to look into it, the magic happens in PackageManagerService.addPreferredActivityInternal(). Looks like it writes the data to a file on disk: package-restrictions.xml. I suppose it's possible you could figure out the format thereof and write the file (you'd need root).
This is controlled by a system settings, "stay_on_while_plugged_in". You can set it using adb shell settings system put ....
The TTS engine is stored in a secure setting, "tts_default_synth". You can see the value like,
$ adb shell settings get secure tts_default_synth com.svox.pico
com.svox.pico
And you can set it with adb shell settings put secure "tts_default_synth" <the value>.
I noticed that if the value was not been previously set, when you get the value using the settings command you get null and it's not listed in settings list, even though there is a default value. As of Android 6 (I think), settings are no longer in a DB but rather are stored in XML files in /data/system/users/0/settings_*.xml. You can see the values therein.
Since I'm working in a platform which works with many apps (rather than a single target app), I find the selection of a target app inefficient for my needs. I wondered if I could do something to avoid it.
I'd like to run freely, sending UI commands to iOS and Android real devices, including installing an app from another app (like Play Store, Apple Store, Test Flight, etc.)
Thanks for the help,
David.
The rule is: 1 Webdriver instance per application.
You can run Appium's server with no --app argument by making sure auto-launch is set to false, and not setting bundleId or app.
Then, in your client/test framework, you use several webdrivers, configured to use different desired capabilities, to tie it all together under a single test case/suite.
The solution:
You may have a test suite that sets desired_capabilities to launch the Safari app, then you install the app, then you quit the webdriver.
Then you change the desired_capabilities to point to the bundle_id of the new app, launch another webdriver instance, do your tests, quit the webdriver..
Then you change the desired_capabilities to point to (etc., etc.)
driver = webdriver.new(url, desired_capabilities)
// do some stuff
driver.quit()
desired_capabilities['app'] = 'company.app.com'
driver = webdriver.new(url, desired_capabilities)
// do some stuff
driver.quit()
desired_capabilities['app'] = '/path/to/application.app'
driver = webdriver.new(url, desired_capabilities)
// do some stuff
driver.quit()