Caching issue in uiautomator - android-testing

I have an android app. I am doing automated testing of this app using uiautomator.
Before doing any processing I need to login the app. But at first time it store the data in cache and login automatically every time when I launch.
I want application should be logged in every time with filled credential.
Is there any way to stop this caching by using uiautomator api.

For those of you who wants to clear your target app under test, while running UiAutomator, you could probably try the method I wrote below. This only works with API level 18 or greater.
http://developer.android.com/reference/android/app/UiAutomation.html#executeShellCommand(java.lang.String)
public static void clearData (String packageName) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.executeShellCommand("pm clear " + packageName)
.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}

You can give below command before you start your tests, this would clear you application data. Then start your tests !
adb shell pm clear yourPackageName

In your app you can manually first clear the data or disable the "Save my credential" option in the app. So every time when starting the app it will ask for the credentials again.
Or else you can directly write it in command prompt before running the test case.
adb shell pm clear yourPackageName

Related

Schedule Turn on/off android device programmatically on specific times

Hell all,
I am developing an android app on rooted device, and I need the power off this device on specific time say on 12:00 AM, and power on again after 8 hours, say on 8:00 AM.
I did a search on the internet, and I found some lines of code that do the shutdown process, the code is:
try {
Process proc = Runtime.getRuntime()
.exec(new String[]{ "su", "-c", "reboot -p" });
proc.waitFor();
} catch (Exception ex) {
ex.printStackTrace();
}
The above code will shutdown the device only on rooted ones, what I need now is to create some timer or some line of code which will turn the device on on the desired time. any ideas?
Thanks
this is simply not possible, once you turn it off you lose control over the device.

How to test if Xamarin Android app closes

I am writing my first Android app, using Xamarin. I have an Exit button that, when clicked, closes the app. I want a test in Xamarin UITest that verifies clicking the button closes the app. I messed around with it for a while and finally found something that allows the test to pass.
In the app:
exitButton.Click += (o, e) =>
{
int pid = Android.OS.Process.MyPid();
Android.OS.Process.KillProcess(pid);
};
In UITest:
[Test]
public void ExitButtonClosesTheScreen()
{
try
{
app.Tap(c => c.Button("exitButton"));
Assert.Fail("App remains open.");
}
catch (System.Exception e)
{
Assert.AreEqual("The underlying connection was closed: The connection was closed unexpectedly.", e.InnerException.InnerException.InnerException.Message);
}
}
The test now passes so I guess I'm happy. My question is, is this really the best way to do this? Or is there a better way that I wasn't able to find?
Edit: Unfortunately, this is not the answer. This method allows the test to pass in VS but fails when I run it in App Center. Is there another way to run this test? Or is this something that is simply not testable with UITest? Thank you.
First of all the right code for closing the Application as per me is using finish affinity
In an Activity:
this.FinishAffinity();
In a Fragment:
this.Activity.FinishAffinity();
After doing this AppCenter should be able to figure that your app is closed.
I did a brief read up on this the other day for something similar and I am certain that the ActivityManager class would be the best way to go about this.
https://developer.xamarin.com/api/type/Android.App.ActivityManager/
There is a method within this class called RunningAppProcesses which returns a list of application processes that are running on the device - and from there I guess you can assert if your app process is on the list or not.
Hope this helps
After almost 4 years, i've encountered with the same issue.
I will do it this way in your case:
[Test]
public void ExitButtonClosesTheScreen()
{
app.Tap(c => c.Marked("exitButton"));
/** I asume exitButton click action will just exit,
no popups or alerts appear before exiting. **/
app.WaitForNoElement(q => q.Marked("exitButton"),
"Timeout waiting for element exitButton",
new TimeSpan(0, 0, 30));
AppResult[] result = app.Query();
Assert.IsTrue(result.Length == 0);
}
app.Query() returns all views visible by default, unless a query is especified by a lambda expression, as you should alredy know.
If the Application is gone, the Views visible will be 0, and as such, app.query() will return and array lenght of 0.
For WaitForNoElement's timeout I use a TimeSpan of 30 seconds, but you can use whatever timeout you prefer for this operation, i just considered 30 seconds will be ok.

Losing webdriverio session when testing electron app restart using spectron

I'm using spectron to run integration tests against my electron app. Everything is working fine apart from attempting to test that app settings are persisted properly between app restarts.
While running tests, my app starts up with new temporary userData directory for every test which ensures that the tests are isolated. This means the the persistence testing needs to ideally occur in a single test and to achieve this I have to restart the app in the middle of the test. There's an app.restart method so this has got to be supported right?
I'm using the following spectron test code:
// save some settings here
await app.restart();
await app.client.waitUntilWindowLoaded()
// do some more checking to ensure the app is fully loaded
// check the settings here
However I'm getting the following error:
Error: waitUntilWindowLoaded Promise was rejected with the following reason:
Error: A session id is required for this command but wasn't found in the response payload
What's the correct way to do this? I've also tried stopping the Application instance and starting a new one with similar results.
This appears to work
// save some settings here
await app.stop();
app = new Application({ ... });
await app.start();
await app.client.waitUntilWindowLoaded();
// do some more checking to ensure the app is fully loaded
// check the settings here
Following snippsets works,
import test from 'ava'
import util from '../util'
test(async t => {
// This runs after each test and other test hooks, even if they failed
let app = util.createApp()
app = await util.waitForLoad(app, t)
await app.restart()
await app.client.waitUntilWindowLoaded()
// app = await util.waitForLoad(app, t)
})
works with, "spectron": "^3.5.0"

Reset app state between InstrumentationTestCase runs

One of my QA engineers is supporting an app with a fairly large codebase and a lot of different SharedPreferences files. He came to me the other day asking how to reset the application state between test runs, as if it had been uninstalled-reinstalled.
It doesn't look like that's supported by Espresso (which he is using) nor by the Android test framework natively, so I'm not sure what to tell him. Having a native method to clear all the different SharedPreferences files would be a pretty brittle solution.
How can one reset the application state during instrumentation?
Current espresso doesn't provide any mechanism to reset application state. But for each aspect (pref, db, files, permissions) exist a solution.
Initial you must avoid that espresso starts your activity automatically so you have enough time to reset.
#Rule
public ActivityTestRule<Activity> activityTestRule = new ActivityTestRule<>(Activity.class, false, false);
And later start your activity with
activityTestRule.launchActivity(null)
For reseting preferences you can use following snippet (before starting your activity)
File root = InstrumentationRegistry.getTargetContext().getFilesDir().getParentFile();
String[] sharedPreferencesFileNames = new File(root, "shared_prefs").list();
for (String fileName : sharedPreferencesFileNames) {
InstrumentationRegistry.getTargetContext().getSharedPreferences(fileName.replace(".xml", ""), Context.MODE_PRIVATE).edit().clear().commit();
}
You can reset preferences after starting your activity too. But then the activity may have already read the preferences.
Your application class is only started once and already started before you can reset preferences.
I have started to write an library which should make testing more simple with espresso and uiautomator. This includes tooling for reseting application data. https://github.com/nenick/espresso-macchiato See for example EspAppDataTool with the methods for clearing preferences, databases, cached files and stored files.
Improving on #nenick's solution, encapsulate the state clearing behavior in a custom ActivityTestRule. If you do this, you can allow the test to continue to launch the activity automatically without intervention from you. With a custom ActivityTestRule, the activity is already in the desired state when it launches for the test.
Rules are particularly useful because they're not tied to any specific test class, so can be easily reused within any test class or any project.
Below is one I implemented to ensure that the app is signed out when the activity launches, per test. Some tests, when they failed, were leaving the app in a signed in state. This would then cause later tests to also fail because the later ones assumed they would need to sign in, but the app would already be signed in.
public class SignedOutActivityTestRule<T extends Activity> extends ActivityTestRule<T> {
public SignedOutActivityTestRule(Class<T> activityClass) {
super(activityClass);
}
#Override
protected void beforeActivityLaunched() {
super.beforeActivityLaunched();
InstrumentationRegistry.getTargetContext()
.getSharedPreferences(
Authentication.SHARED_PREFERENCES_NAME,
Context.MODE_PRIVATE)
.edit()
.remove(Authentication.KEY_SECRET)
.remove(Authentication.KEY_USER_ID)
.apply();
}
}
you can try add this to gradle:
android {
...
defaultConfig {
...
testInstrumentationRunnerArguments clearPackageData: 'true'
}
}
refer to https://developer.android.com/training/testing/junit-runner
To remove all shared state from your device's CPU and memory after each test, use the clearPackageData flag.

detect when blackberry App is Auto-started at boot up time vs started by user

I want to have my app automatically run at start time in order to register with the HttpFilterRegistry. I know how to make my app auto-start but what I'm really after is differentiating between when the sytem starts the app and when the user starts the app. If the user is starting the app, I want to just show the GUI. If it's the system, I want to just register the HTTP filters.
Is this possible?
When you create your Alternate Entry Point, specify an "Application argument". When the app launches you can do this in your main() method
//Autostart
if( args != null && args.length > 0 && args[0].equals("the_application_argument")) {
//register HTTP filters
}
//User start
else{
//launch the GUI
}
there is a function called inStartup() in application Manager class
Determines if the device is in the process of starting up. so you can check on it.
i think its better than create new entry point and pass an arguments to main

Resources