sqlite Android测试-每次测试都从干净的数据库开始

j0pj023g  于 2023-01-09  发布在  SQLite
关注(0)|答案(6)|浏览(141)

我正在使用Android Instrumentation测试来测试我的应用程序。
所以我有一个扩展ActivityInstrumentationTestCase2的测试类,它包含了多个测试。

public class ManageProjectsActivityTestextends ActivityInstrumentationTestCase2<ManageProjectsActivity> {
    public ManageProjectsActivityTest() {
        super("eu.vranckaert.worktime", ManageProjectsActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
        getInstrumentation().getTargetContext().deleteDatabase(DaoConstants.DATABASE);
        super.setUp();
        solo = new Solo(getInstrumentation(), getActivity());
    }

    @Override
    protected void runTest() throws Throwable {
        super.runTest();
        getActivity().finish();
    }

    public void testDefaults() {
        // My test stuff
    }

    public void testAddProject() {
        // My test stuff
    }
}

因此,测试中的活动有一个项目列表,项目列表是从数据库中获取的,当没有可用的数据库时,当创建数据库时,我插入一个默认项目。
这意味着当测试运行时,我会执行以下操作:
1.数据库(如果可用)将从设备上删除
1.启动第一个测试(因此启动了使用一个项目创建我的DB的活动)
1.测试使用新创建的DB,也就是说只有一个项目,在测试期间会创建第二个项目
1.第一个测试完成后,将再次调用setUp()方法
1.现在应该存在的数据库再次被删除
1.启动第二个测试(因此启动了使用一个项目创建我的DB的活动)
1.第二个测试也将完成
但这并不是这个测试套件所做的......这是我的测试套件的结果:
1.数据库(如果可用)将从设备上删除
1.启动第一个测试(因此启动了使用一个项目创建我的DB的活动)
1.测试使用新创建的DB,也就是说只有一个项目,在测试期间会创建第二个项目
1.第一个测试完成后,将再次调用setUp()方法
1.现在应该存在的数据库再次被删除
1.它来了第二个测试开始(但我的数据库没有再次创建!!!我也看不到设备上的文件...),测试开始时应该只显示一个项目,但实际上已经显示了两个!!!
1.第二个测试也完成了,但失败了,因为我一开始有两个项目...
一开始,我没有覆盖runTest()方法,但我想也许我应该自己结束活动以强制重新创建,但这没有任何区别。
因此,DB似乎保留在内存中(因为即使显式删除它,也不会在设备上创建新的DB文件),甚至Activity也是如此,因为在Activity的onCreate中放置断点a时,两个测试都只会进入一次。
为了维护数据库,我使用了ORMLite。你可以在这里看到我的助手类:http://code.google.com/p/worktime/source/browse/trunk/android-app/src/eu/vranckaert/worktime/dao/utils/DatabaseHelper.java
所以我的问题是如何强制测试始终使用不同的DB...?

qxgroojn

qxgroojn1#

与这个问题有点关联,但我在寻求帮助时来到了这里。可能对一些人有帮助。如果你用RenamingDelegatingContext初始化你的数据库,它会在运行之间清理数据库。

public class DataManagerTest extends InstrumentationTestCase {

  private DataManager subject;

  @Before
  public void setUp() {
    super.setUp();

    RenamingDelegatingContext newContext = new RenamingDelegatingContext(getInstrumentation().getContext(), "test_");
    subject = new DataManager(newContext);
  }

  // tests...
}

和关联的数据管理器类。

public class DataManager {

    private SQLiteDatabase mDatabase;
    private SQLiteOpenHelper mHelper;
    private final String mDatabaseName = "table";
    private final int mDatabaseVersion = 1;

    protected DataManager(Context context) {
    this.mContext = context;
    createHelper();
  }

  private void createHelper() {
    mHelper = new SQLiteOpenHelper(mContext, mDatabaseName, null, mDatabaseVersion) {
      @Override
      public void onCreate(SQLiteDatabase sqLiteDatabase) {
        // createTable...
      }

      @Override
      public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
        // upgrade table
      }
    };
  }
    ...
}
pdkcd3nj

pdkcd3nj2#

mDb.delete(DATABASE_TABLE_NAME, null, null);

这确实是解决办法/可行之道...
我将setUp(..)方法中的第一行更改为:

cleanUpDatabase(tableList);

然后我添加了方法cleanUpDatabasese(..),类似于:

private void cleanUpDatabase(List<String> dbTables) {
    Log.i(LOG_TAG, "Preparing to clean up database...");
    DatabaseHelper dbHelper = new DatabaseHelper(getInstrumentation().getTargetContext());
    ConnectionSource cs = dbHelper.getConnectionSource();
    SQLiteDatabase db = dbHelper.getWritableDatabase();

    Log.i(LOG_TAG, "Dropping all tables");
    for (String table : dbTables) {
        db.execSQL("DROP TABLE IF EXISTS " + table);
    }

    Log.i(LOG_TAG, "Executing the onCreate(..)");
    dbHelper.onCreate(db, cs);

    Log.i(LOG_TAG, "Verifying the data...");
    for (String table : dbTables) {
        Cursor c = db.query(table, new String[]{"id"}, null, null, null, null, null);
        int count = c.getCount();
        if (count != 1 && (table.equals("project") || table.equals("task"))) {
            dbHelper.close();
            Log.e(LOG_TAG, "We should have 1 record for table " + table + " after cleanup but we found " + count + " record(s)");
            throw new RuntimeException("Error during cleanup of DB, exactly one record should be present for table " + table + " but we found " + count + " record(s)");
        } else if (count != 0 && !(table.equals("project") || table.equals("task"))) {
            dbHelper.close();
            Log.e(LOG_TAG, "We should have 0 records for table " + table + " after cleanup but we found " + count + " record(s)");
            throw new RuntimeException("Error during cleanup of DB, no records should be present for table " + table + " but we found " + count + " record(s)");
        }
    }

    Log.i(LOG_TAG, "The database has been cleaned!");
    dbHelper.close();
}

这段代码在每个测试之前执行,这使得我的所有测试彼此独立。

警告:为了检索对您的DatabaseHelper的引用(您自己的实现偏离了轨道;))您不能调用getActivity(),因为这将启动您的活动(并因此执行所有初始DB加载(如果有..)

hjqgdpho

hjqgdpho3#

仪器注册表→获取上下文→删除数据库

android.support.test.InstrumentationRegistrygetTargetContext和可能与直觉相反的getContext应该可以实现这个功能:

概要

使用 * getContext * 删除数据库(不是*getTargetContext *)。
getContext().deleteDatabase(DbHelper.DATABASE_NAME);

示例

public class DbHelperTest {
private DbHelper mDb;

    @Before
    public void setUp() throws Exception {
        getContext().deleteDatabase(DbHelper.DATABASE_NAME);
        mDb = new DbHelper(getTargetContext());
    }

    @After
    public void tearDown() throws Exception {
        mDb.close();
    }

    @Test
    public void onCreate() throws Exception {
        mDb.onCreate(mDb.getWritableDatabase());
    }

    @Test
    public void onUpgrade() throws Exception {
        mDb.onUpgrade(mDb.getWritableDatabase(), 1, 2);
    }

    @Test
    public void dropTable() throws Exception {
        String tableName = "mesa";
        mDb.getReadableDatabase().execSQL("CREATE TABLE "
            + tableName + "(_id INTEGER PRIMARY KEY AUTOINCREMENT)");
        mDb.dropTable(mDb.getWritableDatabase(), tableName);
    }
}
mqxuamgl

mqxuamgl4#

您尝试开始时间所有表数据删除更改本机解决方案。

mDb.delete(DATABASE_TABLE_NAME, null, null);
wr98u20j

wr98u20j5#

由于我的数据库是加密的,我需要在每个测试用例后删除实际的数据库文件。我在从RenamingDelegatingContext创建deleteDatabase时遇到了麻烦,因为RenamingDelegatingContext由于某种原因找不到以前创建的数据库。
AndroidTestCase子类的解决方案:

@Override
protected void setUp() throws Exception {
    super.setUp();
    mContext = new RenamingDelegatingContext(getContext(), TEST_DB_PREFIX);

   // create db here
}

@Override
protected void tearDown() throws Exception {
    // Making RenamingDelegatingContext find the test database
    ((RenamingDelegatingContext) mContext).makeExistingFilesAndDbsAccessible();
     mContext.deleteDatabase(DB_NAME);

    super.tearDown();
}
ilmyapht

ilmyapht6#

在每次测试运行它之前

val context: Context = ApplicationProvider.getApplicationContext()
context.deleteDatabase("myDatabaseName.db")

这也可以作为一个规则

相关问题