Skip to content

Commit

Permalink
Clear Database Test Rule (#29)
Browse files Browse the repository at this point in the history
* Implemented ClearDatabaseRule

Creates Activity and test to check if database is cleared

* Fixed PMD violation

* Fixed checkstyle violations

* Renamed SqliteOpenHelper for clarity

* Extracted database version to a constant for clarity

* Changed database name to help identify it

* Added ClearDatabaseRule to the readme
  • Loading branch information
Sloy authored Apr 4, 2017
1 parent 6cc87a3 commit 535108e
Show file tree
Hide file tree
Showing 9 changed files with 302 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,11 @@ PermissionGranter.allowPermissionsIfNeeded(Manifest.permission.GET_ACCOUNTS);

## Resetting the app's data before running each test

As tests should be isolated, they need to set the environment before running. As Espresso doesn't help achieving it, Barista offers a set of rules to clear the app's data before running each test.
As tests should be isolated, they need to set the environment before running. Espresso doesn't help achieving it but Barista offers a set of rules to clear the app's data before running each test.

```java
@Rule public ClearPreferencesRule clearPreferencesRule = new ClearPreferencesRule(); // Clear all app's SharedPreferences
@Rule public ClearDatabaseRule clearDatabaseRule = new ClearDatabaseRule(); // Delete all tables from all the app's SQLite Databases
```

## Dealing with Flaky tests
Expand Down
2 changes: 2 additions & 0 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ dependencies {
}
compile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
compile 'com.android.support:support-annotations:25.1.0'
testCompile 'junit:junit:4.12'
testCompile 'org.assertj:assertj-core:1.7.0'
}

publish {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.schibsted.spain.barista.cleardata;

import android.content.Context;
import android.support.test.InstrumentationRegistry;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

/**
* This rule clears all app's Databases before running each test
*/
public class ClearDatabaseRule implements TestRule {

@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
clearData();
base.evaluate();
clearData();
}
};
}

private void clearData() {
DatabaseOperations.clearAllDatabases(getAppContext());
}

private Context getAppContext() {
return InstrumentationRegistry.getTargetContext();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.schibsted.spain.barista.cleardata;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.support.annotation.VisibleForTesting;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class DatabaseOperations {

private static final String[] UNWANTED_FILENAME_SUFFIXES = new String[] {
"-journal",
"-shm",
"-uid",
"-wal"
};

static void clearAllDatabases(Context appContext) {
for (File file : getDatabaseFiles(appContext)) {
clearDatabase(file);
}
}

private static void clearDatabase(File databaseFile) {
SQLiteDatabase database = openDatabase(databaseFile);
try {
List<String> tables = getTableNames(database);

for (String table : tables) {
deleteTableContent(database, table);
}
} finally {
database.close();
}
}

private static List<File> getDatabaseFiles(Context context) {
List<File> allDatabaseFiles = new ArrayList<>();
for (String databaseName : context.databaseList()) {
allDatabaseFiles.add(context.getDatabasePath(databaseName));
}
return filterUnwantedDatabaseFiles(allDatabaseFiles);
}

@VisibleForTesting
static List<File> filterUnwantedDatabaseFiles(List<File> allDatabaseFiles) {
List<File> filteredList = new ArrayList<>();
for (File databaseFile : allDatabaseFiles) {
if (!hasUnwantedSuffix(databaseFile)) {
filteredList.add(databaseFile);
}
}
return filteredList;
}

private static boolean hasUnwantedSuffix(File databaseFile) {
String databaseName = databaseFile.getPath();
for (String suffix : UNWANTED_FILENAME_SUFFIXES) {
if (databaseName.endsWith(suffix)) {
return true;
}
}
return false;
}

private static SQLiteDatabase openDatabase(File databaseFile) {
return SQLiteDatabase.openDatabase(
databaseFile.getAbsolutePath(),
null /* cursorFactory */,
0 /* flags */);
}

private static List<String> getTableNames(SQLiteDatabase database) throws SQLiteException {
Cursor cursor = database.rawQuery("SELECT name FROM sqlite_master WHERE type IN (?, ?)", new String[] { "table", "view" });
try {
List<String> tableNames = new ArrayList<>();
while (cursor.moveToNext()) {
tableNames.add(cursor.getString(0));
}
return tableNames;
} finally {
cursor.close();
}
}

private static void deleteTableContent(SQLiteDatabase database, String table) {
database.delete(table, null, null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.schibsted.spain.barista.cleardata;

import java.io.File;
import java.util.List;
import org.junit.Test;

import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;

public class DatabaseOperationsTest {

@Test
public void filtersUnwantedDatabaseFiles() throws Exception {
List<File> allFiles = asList(
new File("my_database.db"),
new File("my_database.db-journal"),
new File("my_database.db-shm"),
new File("my_database.db-uid"),
new File("my_database.db-wal"),
new File("another_database")
);
List<File> expectedFiles = asList(
new File("my_database.db"),
new File("another_database")
);

List<File> filteredFiles = DatabaseOperations.filterUnwantedDatabaseFiles(allFiles);

assertThat(filteredFiles).containsExactlyElementsOf(expectedFiles);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.schibsted.spain.barista.sample;

import android.support.test.rule.ActivityTestRule;
import com.schibsted.spain.barista.BaristaClickActions;
import com.schibsted.spain.barista.cleardata.ClearDatabaseRule;
import org.junit.Rule;
import org.junit.Test;

import static com.schibsted.spain.barista.BaristaAssertions.assertDisplayed;

public class ClearDatabaseRuleTest {

@Rule
public ActivityTestRule<DatabaseActivity> activityRule = new ActivityTestRule<>(DatabaseActivity.class, true, false);

@Rule
public ClearDatabaseRule clearDatabaseRule = new ClearDatabaseRule();

//
// Only one of these two tests will succeed when database is not cleared.
// They rely on database being cleared between test executions.
//

@Test
public void checkOnceThatValueIsZeroFistAndOneAfterIncrement() throws Exception {
activityRule.launchActivity(null);

assertCurrentValueIs("0");
incrementValue();
assertCurrentValueIs("1");
}

@Test
public void checkTwiceThatValueIsZeroFistAndOneAfterIncrement() throws Exception {
activityRule.launchActivity(null);

assertCurrentValueIs("0");
incrementValue();
assertCurrentValueIs("1");
}

private void assertCurrentValueIs(String expectedValue) {
assertDisplayed(expectedValue);
}

private void incrementValue() {
BaristaClickActions.click(R.id.database_increment_button);
}
}
1 change: 1 addition & 0 deletions sample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<activity android:name=".ViewPagerActivity"/>
<activity android:name=".DialogActivity"/>
<activity android:name=".PreferencesActivity"/>
<activity android:name=".DatabaseActivity"/>
<activity android:name=".HelloWorldActivity"/>
<activity android:name=".NavigationDrawerActivity"
android:theme="@style/AppTheme.NoActionBar">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.schibsted.spain.barista.sample;

import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class DatabaseActivity extends Activity {

private TextView currentValueText;
private DatabaseOpenHelper databaseOpenHelper;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_database);

databaseOpenHelper = new DatabaseOpenHelper(this);
currentValueText = ((TextView) findViewById(R.id.database_current_value));
findViewById(R.id.database_increment_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
incrementValue();
showCurrentValue();
}
});

showCurrentValue();
}

private void showCurrentValue() {
SQLiteDatabase readableDatabase = databaseOpenHelper.getReadableDatabase();
Cursor cursor = readableDatabase.query("User", new String[] { "name" }, null, null, null, null, null);

int currentValue = cursor.getCount();
currentValueText.setText(String.valueOf(currentValue));

cursor.close();
readableDatabase.close();
}

private void incrementValue() {
SQLiteDatabase writableDatabase = databaseOpenHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues(1);
contentValues.put("name", "Mr T");
writableDatabase.insert("User", null, contentValues);
writableDatabase.close();
}

private static class DatabaseOpenHelper extends SQLiteOpenHelper {

private static final int DB_VERSION = 1;

DatabaseOpenHelper(Context context) {
super(context, "mydatabase.db", null, DB_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE User (name TEXT NOT NULL);");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}
}
}
19 changes: 19 additions & 0 deletions sample/src/main/res/layout/activity_database.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>

<TextView
android:id="@+id/database_current_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/database_increment_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Increment value"
/>
</LinearLayout>

0 comments on commit 535108e

Please sign in to comment.