Norbert
Norbert

Reputation: 1037

Android, run regular app in instrumentation mode (adb + debug only)

I'd like to run an Android app in a way that it can access InstrumentationRegistry.getInstrumentation() during the runtime.

This is only for debug builds and installing the app through ADB is sufficient. Because I don't want to use the instrumentation test-suite, I don't want to use InstrumentationTestRunner but launch the MainActivity of the app directly.

How is this possible?

What I've tried:

  1. Added regular implementation dependency on test packages (instead of test only dependency) - worked
    implementation 'androidx.test.uiautomator:uiautomator:2.2.0'
    implementation 'androidx.test:runner:1.1.0'
  1. Added instrumentation to manifest
    <instrumentation android:name=".MainActivity"
        android:targetPackage="com.android.shell"
        android:label="App" />

(Not sure whether this is actually correct.)

  1. Ran the app using (app already installed on the device)
adb shell am instrument -w com.example.app/.MainActivity         

This results in:

android.util.AndroidException: INSTRUMENTATION_FAILED: com.example.app/com.example.app.MainActivity
    at com.android.commands.am.Instrument.run(Instrument.java:519)
    at com.android.commands.am.Am.runInstrument(Am.java:202)
    at com.android.commands.am.Am.onRun(Am.java:80)
    at com.android.internal.os.BaseCommand.run(BaseCommand.java:60)
    at com.android.commands.am.Am.main(Am.java:50)
    at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
    at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:399)

So essentially my question is, how do I achieve running the app in a way I can use UiAutomator during the runtime?

Thanks in advance!

Upvotes: 5

Views: 1066

Answers (1)

Heitor Paceli
Heitor Paceli

Reputation: 530

Yes, it is possible:

1. Add the dependencies to your build.gradle. It should be like this:

implementation 'androidx.test.ext:junit:1.1.2'
implementation 'androidx.test.uiautomator:uiautomator:2.2.0'
implementation 'androidx.test:runner:1.1.0'

2. Add the following uses-library inside application tag and instrumentation inside manifest in you AndroidManifest.xml:

    <!-- Add inside application tag -->
    <uses-library android:name="android.test.runner" />

Set android:targetPackage to your own application package name.

    <!-- Add inside manifest tag -->
    <instrumentation
        android:name="androidx.test.runner.AndroidJUnitRunner"
        android:label="App"
        android:targetPackage="com.example.app" />
    </manifest>

3. Create your activity. You can use InstrumentationRegistry.getInstrumentation(); there.

4. Create you Test class in the same source set of your application classes (inside src/main/java)

    @RunWith(AndroidJUnit4.class)
    public class Test {
        @org.junit.Test
        public void test() {
            // Put any code here. It is launching the activity.
            Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
            Context context = instrumentation.getTargetContext();
            Intent intent = new Intent(context, MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        }
    }

5. Build and install the app.

6. Run the app using: adb shell am instrument -w -m -e debug false -e class 'com.example.app.Test' com.example.app/androidx.test.runner.AndroidJUnitRunner

7. (Optional) If you want to execute it directly from the run button in Android Studio, then add this inside android in your build.gradle, it will change the place where the test classes must be created, pointing to the same folder as the main code:

sourceSets {
    androidTest {
        java.srcDir 'src/main/java'
    }
}

Upvotes: 3

Related Questions