Razzle Shazl
Razzle Shazl

Reputation: 1330

Android Studio -- clear application data for Instrumentation Test

How can I get Android Studio (AndroidJunitRunner) to clear application data preceding an instrumentation test without manually running adb command?

I discovered that android.support.test.runner.AndroidJUnitRunner kind of cheats -- it never actually invokes connectedCheck or connectedAndroidTest.

  1. When run from command line $ gradle connectedCheck

    :MyMainApp:assembleDebug UP-TO-DATE
    :MyMainApp:assembleDebugTest UP-TO-DATE
    :MyMainApp:clearMainAppData
    :MyMainApp:connectedCheck
    
  2. When run from within IDE by clicking the instrumentation test configuration (green Android robot logo with red/green arrows)

    **Executing tasks: [:MyMainAppApp:assembleDebug, :MyMainAppApp:assembleDebugTest]**
    

    As you can see, the last gradle target is assembleDebugTest

I had added a hook onto connectedCheck in build.gradle to clear the data of the main app before starting the instrumentation test.

// Run 'adb' shell command to clear application data of main app for 'debug' variant
task clearMainAppData(type: Exec) {
    // we have to iterate to find the 'debug' variant to obtain a variant reference
    android.applicationVariants.all { variant ->
        if (variant.name.equals("debug")) {
            def clearDataCommand = ['adb', 'shell', 'pm', 'clear', getPackageName(variant)]
            println "Clearing application data of ${variant.name} variant: [${clearDataCommand}]"
            commandLine clearDataCommand
        }
    }
}
// Clear Application Data (once) before running instrumentation test
tasks.whenTaskAdded { task ->
    // Both of these targets are equivalent today, although in future connectedCheck
    // will also include connectedUiAutomatorTest (not implemented yet)
    if(task.name.equals("connectedAndroidTest") || task.name.equals("connectedCheck" )){
        task.dependsOn(clearMainAppData)
    }
}

I realize that alternatively I could implement a 'clear data' button in the main app and have the instrumentation app click through the UI, but I find that solution undesirable.

I looked at AndroidJUnitRunner API and there are hooks via Runlistener interface but hooks are during the context of the test app, i.e. running on device, and Android forbids one app from modifying another app. http://junit.sourceforge.net/javadoc/org/junit/runner/notification/RunListener.html

Best answer goes to you if you can help me trigger one of the following automatically from within Android Studio:

I'm also all ears if there is an alternate way. Surely with device testing automation there should be a clear way to clear application data?

Thank you!

Upvotes: 23

Views: 21931

Answers (3)

tasjapr
tasjapr

Reputation: 1230

Solution in 2023

  1. Add dependencies (check actual versions here) :

With Gradle:

dependencies {
    androidTestImplementation 'androidx.test:runner:1.5.2'
    androidTestUtil 'androidx.test:orchestrator:1.4.2'
}

With version catalog:

[versions]
testRunner = "1.5.2"
orchestrator = "1.4.2"

[libraries]
orchestrator = { group = "androidx.test", name = "runner", version.ref = "testRunner" }
orchestrator = { group = "androidx.test", name = "orchestrator", version.ref = "orchestrator" }

  1. Modify gradle file. Add the following statements to your project's build.gradle file:

Kotlin:

defaultConfig {
    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
      
    // The following argument makes the Android Test Orchestrator run its
    // "pm clear" command after each test invocation. This command ensures
    // that the app's state is completely cleared between tests.
    testInstrumentationRunnerArguments += mapOf(
            "clearPackageData" to "true",
        )
}

testOptions {
    execution = "ANDROIDX_TEST_ORCHESTRATOR"
}

Groovy:

defaultConfig {
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
  testInstrumentationRunnerArguments clearPackageData: 'true'
}

testOptions {
  execution 'ANDROIDX_TEST_ORCHESTRATOR'
}

Android Developers docs

Upvotes: 0

Ponsuyambu
Ponsuyambu

Reputation: 8926

With Android Test Orchestrator it is easier to provide this option via gradle script.

android {
  defaultConfig {
   ...
   testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

   // The following argument makes the Android Test Orchestrator run its
   // "pm clear" command after each test invocation. This command ensures
   // that the app's state is completely cleared between tests.
   testInstrumentationRunnerArguments clearPackageData: 'true'
 }

Below is the link for Android Test Orchestrator

https://developer.android.com/training/testing/junit-runner#using-android-test-orchestrator

Upvotes: 26

NSimon
NSimon

Reputation: 5287

I know it's been a while, and hopefully by now you will have this issue sorted.

I ran into that same issue today, and crashed here without any solution.

But I managed to make it work by calling my task from the test configuration.

Step 1 : Go to your test configuration

Your test configuration

Step 2 : Simply add the gradle task you created

Simply call your gradle task from here

By the way, the task in my case simply looks like this :

task clearData(type: Exec) {
  def clearDataCommand = ['adb', 'shell', 'pm', 'clear', 'com.your.application']
  commandLine clearDataCommand
}

Hope this will help someone :)

Upvotes: 32

Related Questions