4

im using espresso to clear database in my app Im setting activity like this

@Rule
@JvmField
val activity = ActivityTestRule<PhotoPrinterActivity>(PhotoPrinterActivity::class.java,false,false)

And this is my before function

@Before
open fun setup() {
    clearDatabase()
    activity.launchActivity(null)
    // Waiting for start app success fully

}

And this is my clear database code

fun clearDatabase() {
    val databaseList = InstrumentationRegistry.getInstrumentation().targetContext.databaseList()
    for (database in databaseList) {

        // when transaction rollback files exists they are always locked so we can't delete them
        if (database.contains(".db-journal")) {
            InstrumentationRegistry.getTargetContext().deleteDatabase(database)
            continue
        }

        // when using transaction write ahead logging then this db files are listed but often they don't exist
        if (database.contains(".db-wal") || database.contains(".db-shm")) {
            InstrumentationRegistry.getTargetContext().deleteDatabase(database)
            continue
        }
        Log.v("EspressoMacchiato", "deleting " + database)
        var databasePath = InstrumentationRegistry.getInstrumentation().targetContext.getDatabasePath(database)
        if (databasePath.exists()) {
            InstrumentationRegistry.getInstrumentation().targetContext.deleteDatabase(database)
        }
    }

}

Issue is when clear database success and perform add some data into database,

android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database (code 1032)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:786)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)

Anyone please help me !Thanks so much!

WarrenFaith
  • 57,492
  • 25
  • 134
  • 150
  • 2
    The delete operation may be placing a lock on the database file, which is why you would see this error. Try post a delay on your activity launch to test if that is the case. – Mark OB Feb 08 '18 at 09:15
  • 1
    can you post your database code – sasikumar Feb 08 '18 at 10:04

3 Answers3

9

Use @BeforeClass and InstrumentationRegistry in your espresso tests to delete database:

@BeforeClass
public static void beforeClass() {
    InstrumentationRegistry.getTargetContext().deleteDatabase("database_name");
}

And to prevent bugs when executing multiple espresso tests at once, use Android Test Orchestrator. It will execute all of them separately.

stedi
  • 196
  • 1
  • 5
2

In case you can't make the accepted answer work due to deprecation I believe the Instrumentation api was updated to: InstrumentationRegistry .getInstrumentation() .getTargetContext()

therefore:

InstrumentationRegistry.getInstrumentation().getTargetContext().deleteDatabase("database_name")

Alternatively you can get the actual application context (the "target") you can do :

ApplicationProvider.getApplicationContext<YOUR-APPLICATION>().deleteDatabase("database_name")
HenriqueMS
  • 3,864
  • 2
  • 30
  • 39
0

Clearing the database once per test class

Add the following code to your Android Test class:

companion object {
    @BeforeClass
    fun clearDatabase() {
        InstrumentationRegistry.getInstrumentation().uiAutomation.executeShellCommand("pm clear PACKAGE_NAME").close()
    }
}

Clearing the database before every test

An alternative way to have the database cleared before each test run is to set the clearPackageData flag while using Android Test Orchestrator. This will "remove all shared state from your device's CPU and memory after each test:"

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

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'
 }

  testOptions {
    execution 'ANDROIDX_TEST_ORCHESTRATOR'
  }
}

dependencies {
  androidTestImplementation 'androidx.test:runner:1.1.0'
  androidTestUtil 'androidx.test:orchestrator:1.1.0'
}
Thomas Gales
  • 107
  • 2
  • 8