Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sqlite Android测试-每次测试都从干净的数据库开始_Sqlite - Fatal编程技术网

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

Sqlite Android测试-每次测试都从干净的数据库开始,sqlite,Sqlite,我正在用Android工具测试来测试我的应用程序 因此,我有一个扩展了ActivityInstrumentationTestCase2的测试类,它包含多个测试。代码如下所示: public class ManageProjectsActivityTestextends ActivityInstrumentationTestCase2<ManageProjectsActivity> { public ManageProjectsActivityTest() {

我正在用Android工具测试来测试我的应用程序

因此,我有一个扩展了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
    }
}
public类ManageProjectsActivityTestextends活动检测testcase2{
公共管理项目活动测试(){
super(“eu.vranckaert.worktime”,ManageProjectsActivity.class);
}
@凌驾
受保护的void setUp()引发异常{
getInstrumentation().getTargetContext().deleteDatabase(DaoConstants.DATABASE);
super.setUp();
solo=新的solo(getInstrumentation(),getActivity());
}
@凌驾
受保护的void runTest()抛出可丢弃的{
super.runTest();
getActivity().finish();
}
公共void testDefaults(){
//我的测试材料
}
公共项目(){
//我的测试材料
}
}
因此,正在测试的活动有一个项目列表。 从数据库中检索项目列表。当没有可用的数据库时,因此在创建数据库时,我插入一个默认项目

这意味着当测试运行时,这就是我所说的:

  • 数据库(如果可用)将在设备上删除
  • 启动第一个测试(因此启动活动,用一个项目创建my DB)
  • 测试使用新创建的DB,这意味着只有一个项目,在测试期间会创建第二个项目
  • 第一个测试完成,并再次调用setUp()方法
  • 现在应该存在的数据库再次被删除
  • 启动第二个测试(因此启动活动,用一个项目创建my DB)
  • 第二次测试也完成了
  • 但这并不是这个测试套件的功能。。。 这是我的测试套件的结果:

  • 数据库(如果可用)将在设备上删除
  • 启动第一个测试(因此启动活动,用一个项目创建my DB)
  • 测试使用新创建的DB,这意味着只有一个项目,在测试期间会创建第二个项目
  • 第一个测试完成,并再次调用setUp()方法
  • 现在应该存在的数据库再次被删除
  • 第二个测试开始了(但我的数据库没有被再次创建!!!我也看不到设备上的文件…),测试开始时应该只显示一个项目,但它已经显示了两个
  • 第二次测试也完成了,但失败了,因为我有两个项目在开始
  • 起初,我没有重写runTest()方法,但我认为也许我应该自己结束活动以强制重新创建,但这没有任何区别

    因此,DB似乎保存在内存中(当我显式删除它时,甚至没有在设备上创建新的DB文件)。或者甚至是活动,因为当在活动的onCreate中放置断点a时,对于两个测试,我只会在其中出现一次

    为了维护数据库,我使用了ORMLite。您可以在此处看到我的助手类:


    因此,我的问题是如何强制测试始终使用不同的DB…?

    您尝试启动time all table data delete alter本机解决方案

    mDb.delete(DATABASE_TABLE_NAME, null, null); 
    
    这确实是解决问题的方法

    我将设置(..)方法中的第一行更改为:

    cleanUpDatabase(tableList);
    
    然后我添加了CleanUpdateAbse(..)liek方法:

    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();
    }
    
    private void cleanUpdatebase(列表数据库表){
    Log.i(Log_标签,“准备清理数据库…”);
    DatabaseHelper dbHelper=新的DatabaseHelper(getInstrumentation().getTargetContext());
    ConnectionSource cs=dbHelper.getConnectionSource();
    SQLiteDatabase db=dbHelper.getWritableDatabase();
    Log.i(Log_标签,“删除所有表”);
    for(字符串表:dbTables){
    db.execSQL(“如果存在删除表”+表);
    }
    Log.i(Log_标记,“正在执行onCreate(..”);
    onCreate(db,cs);
    Log.i(Log_标签,“验证数据…”);
    for(字符串表:dbTables){
    游标c=db.query(表,新字符串[]{“id”},null,null,null,null,null);
    int count=c.getCount();
    if(count!=1&(table.equals(“项目”)| | table.equals(“任务”)){
    dbHelper.close();
    Log.e(Log_标记,“我们应该在清理后为表“+table+”创建一条记录,但我们找到了“+count+”记录);
    抛出新的RuntimeException(“在清理数据库时出错,表“+table+”应该只存在一条记录,但我们发现了“+count+”记录”);
    }如果(count!=0&&!(table.equals(“项目”)| | table.equals(“任务”)){
    dbHelper.close();
    Log.e(Log_标记,“在清理之后,表“+table+”应该有0条记录,但我们找到了“+count+”记录);
    抛出新的RuntimeException(“在清理数据库时出错,表“+table+”不应存在任何记录,但我们找到了“+count+”记录”);
    }
    }
    Log.i(Log_标记,“数据库已被清理!”);
    dbHelper.close();
    }
    
    这段代码在每次测试之前执行,这使得我的所有测试彼此独立


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

    与此问题有点不相关,但我在寻求帮助时来到这里。可能对某些人有帮助。如果使用重命名DelegatingContext初始化数据库,它会在运行之间清理数据库

    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...
    }
    
    以及关联的DataManagerClass

    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
          }
        };
      }
        ...
    }
    

    由于我的数据库是加密的,我需要在每个测试用例之后删除实际的数据库文件
    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
          }
        };
      }
        ...
    }
    
    @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();
    }
    
    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);
        }
    }
    
    val context: Context = ApplicationProvider.getApplicationContext()
    context.deleteDatabase("myDatabaseName.db")