Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run an instrument test from within app and wait for result

Tags:

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);

    } 
}
like image 866
Maor Hadad Avatar asked Aug 19 '18 11:08

Maor Hadad


People also ask

What is a instrumented test?

Note: Instrumented test, also known as instrumentation tests, are initialized in a special environment that gives them access to an instance of Instrumentation. This class provides access to the application context and APIs to manipulate the app under test and gives instrumented tests their name.

What are Android Instrumentation tests?

Instrumented tests are tests that run on physical devices and emulators, and they can take advantage of the Android framework APIs and supporting APIs, such as AndroidX Test.


1 Answers

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.

like image 81
Martin Zeitler Avatar answered Oct 26 '22 20:10

Martin Zeitler