29

一部のクラス内で android.database パッケージを使用してデータベースへのアクセスを実装しましたSQLiteOpenHelper(パターン DAO を使用)。

を使用してこれらのクラスのいくつかの junit テストを作成しましたAndroidTestCaseが、これにより、テストでアプリケーションと同じデータベースが使用されます。

ProviderTestCase2orRenamingDelegatingContextを使用してデータベースを個別にテストできることを読みました。残念ながら、ProviderTestCase2/RenamingDelegatingContext を使用してデータベースをテストする方法を示す素晴らしいチュートリアル/例を見つけることができませんでした。

誰か私にどこかを教えてくれますか、ヒントをくれますか、データベース テスト用のコードを共有できますか?!

Cheerrrsss!! ジョルジオ

4

5 に答える 5

21

コンテキスト内で開く前にデータベースが既に存在する場合、ProviderTestCaseとの両方がデータベースを破棄するため、その意味で、SQLite データベースを開くための低レベルのアプローチはどちらも同じです。RenamingDelegatingContext

でフィクスチャ内のデータベースを開くことでこれを活用します。これにより、setUp()各テスト ケースの前に新しいデータベースで作業することが保証されます。

データベース アダプタを作成するよりも、コンテンツ プロバイダを作成することをお勧めします。データが DB に保存されているか、ネットワーク上のどこかに保存されているかにかかわらず、共通のインターフェイスを使用してデータにアクセスできます。コンテンツ プロバイダーの設計は、ほとんどの人が必要とする IPC オーバーヘッドを少し犠牲にして、そのようなデータにアクセスするように調整できます。気にしなくていい。

SQLite データベースにアクセスするためにこれを行った場合、フレームワークは別のプロセスでデータベース接続を完全に管理します。さらにProviderTestCase2<ContentProvider>、コードを 1 行も書かなくても、コンテンツ プロバイダのテスト コンテキストが完全にブートストラップされます。

しかし、自分でブートストラップを行うのはそれほど大きな努力ではないとは言えません。したがって、データベース アダプタ自体があるとします。open()データベースへの書き込みアクセスを取得することに焦点を当てます。

public class MyAdapter {

    private static final String DATABASE_NAME = "my.db";
    private static final String DATABASE_TABLE = "table";
    private static final int DATABASE_VERSION = 1;


    /**
     * Database queries
     */
    private static final String DATABASE_CREATE_STATEMENT = "some awesome create statement";

    private final Context mCtx;
    private SQLiteDatabase mDb;
    private DatabaseHelper mDbHelper;

    private static class DatabaseHelper extends SQLiteOpenHelper {

        public DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(DATABASE_CREATE_STATEMENT);  
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int a, int b) {
            // here to enable this code to compile
        }
    }

    /**
     * Constructor - takes the provided context to allow for the database to be
     * opened/created.
     * 
     * @param context the Context within which to work.
     */
    public MyAdapter(Context context) {
        mCtx = context;
    }

    /**
        * Open the last.fm database. If it cannot be opened, try to create a new
        * instance of the database. If it cannot be created, throw an exception to
        * signal the failure.
        * 
        * @return this (self reference, allowing this to be chained in an
        *         initialization call)
        * @throws SQLException if the database could be neither opened or created
        */
    public MyAdapter open() throws SQLException {
        mDbHelper = new DatabaseHelper(mCtx);
        mDb = mDbHelper.getWritableDatabase();
        return this;
    }

    public void close() {
            mDbHelper.close();
        }

}

次に、テストを次のように記述できます。

public final class MyAdapterTests extends AndroidTestCase {

    private static final String TEST_FILE_PREFIX = "test_";
private MyAdapter mMyAdapter;

@Override
protected void setUp() throws Exception {
    super.setUp();

    RenamingDelegatingContext context 
        = new RenamingDelegatingContext(getContext(), TEST_FILE_PREFIX);

    mMyAdapter = new MyAdapter(context);
    mMyAdapter.open();
}

@Override
protected void tearDown() throws Exception {
    super.tearDown();

    mMyAdapter.close();
    mMyAdapter = null;
}

public void testPreConditions() {
    assertNotNull(mMyAdapter);
}

}

つまり、ここで起こっていることは、 のコンテキスト実装RenamingDelegatingContextMyAdapter(context).open()呼び出されると、常にデータベースを再作成するということです。MyAdapter.DATABASE_CREATE_STATEMENTここで作成する各テストは、呼び出された後のデータベースの状態に対して実行されます。

于 2011-10-11T18:46:42.397 に答える
6

私は実際に SQLiteOpenHelper でデータベースを使用しており、テストのためのトリックがあります。アイデアは、アプリの通常の使用中に標準のオンファイルに保存された DB を使用し、テスト中にインメモリ DB を使用することです。このようにして、標準 DB にデータを挿入/削除/更新することなく、各テストにクリアな DB を使用できます。それは私にとってはうまくいきます。

データベースファイルの名前としてnullを渡すだけで、メモリ内データベースを使用できることに注意してください。これは、API ドキュメントに明確に記載されています。

テスト中にインメモリ DB を使用する利点については、 https ://attakornw.wordpress.com/2012/02/25/using-in-memory-sqlite-database-in-android-tests/ で説明しています。

私のプロジェクトには、SQLiteHelper を拡張する DBHelper クラスがあります。ご覧のとおり、標準的な方法があります。2 つのパラメーターを持つコンストラクターを追加しただけです。違いは、スーパー コンストラクターを呼び出すときに、DB 名として null を渡すことです。

public class DBHelper extends SQLiteOpenHelper {

    public static final int DATABASE_VERSION = 1;
    public static final String DATABASE_NAME = "mydatabase.db";

    public DBHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    public DBHelper(Context context, boolean testMode) {
        super(context, null, null, DATABASE_VERSION);
    }

    public void onCreate(SQLiteDatabase db) {
        //create statements
    }

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //on upgrade policy
    }

    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //on downgrade policy
    }
}

プロジェクト内のすべての「モデル」は、抽象クラスである DBModel を拡張します。

public abstract class DBModel {
    protected DBHelper dbhelper;

    public DBModel(Context context) {
        dbhelper = new DBHelper(context);
    }

    //other declarations and utility function omitted

}

ここで説明したように:コードが JUnit テスト内で実行されているかどうかを確認するにはどうすればよいですか? スタック トレース要素を検索するだけで、JUnit テストを実行しているかどうかを確認する方法があります。結果として、DBModelコンストラクターを変更しました

public abstract class DBModel {
    protected DBHelper dbhelper;

    public DBModel(Context context) {
        if(isJUnitTest()) {
            dbhelper = new DBHelper(context, true);
        } else {
            dbhelper = new DBHelper(context);
        }
    }

    private boolean isJUnitTest() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        List<StackTraceElement> list = Arrays.asList(stackTrace);
        for (StackTraceElement element : list) {
            if (element.getClassName().startsWith("junit.")) {
                return true;
            }
        }
        return false;
    }

    //other declarations and utility function omitted

}

ご了承ください

startsWith("junit.")

多分

startsWith("org.junit.")

あなたの場合。

于 2015-11-17T11:35:09.623 に答える
1

アプリケーションにデータを提供するために、sqlite データベースに支えられた ContentProvider を使用するアプリケーションがあります。

PodcastDataProvider を、アプリケーションが使用する実際のデータ プロバイダーにします。

次に、次のようなテスト プロバイダーを設定できます。

public abstract class AbstractPodcastDataProvider extends ProviderTestCase2<PodcastDataProvider>{
    public AbstractPodcastDataProvider(){
        this(PodcastDataProvider.class, Feed.BASE_AUTH);
    }

    public AbstractPodcastDataProvider(Class<PodcastDataProvider> providerClass,
            String providerAuthority) {
        super(providerClass, providerAuthority);
    }

    public void setUp() throws Exception{
        super.setUp();

        //clear out all the old data.
        PodcastDataProvider dataProvider = 
            (PodcastDataProvider)getMockContentResolver()
            .acquireContentProviderClient(Feed.BASE_AUTH)
            .getLocalContentProvider();
        dataProvider.deleteAll();
    }
}

実際のアプリケーションとは異なるデータベースによってサポートされるテスト データ プロバイダーをセットアップします。

DAO をテストするには、AbstractPodcastDataProvider を拡張する別のクラスを作成し、

getMockContentResolver();

メソッドを使用して、アプリケーション データベースの代わりにテスト データベースを使用するコンテンツ リゾルバーのインスタンスを取得します。

于 2011-05-27T18:59:15.230 に答える
0
private static String db_path = "/data/data/android.testdb/mydb";
private SQLiteDatabase sqliteDatabase = null;
private Cursor cursor = null;
private String[] fields;

/*
 * (non-Javadoc)
 * 
 * @see dinota.data.sqlite.IDataContext#getSQLiteDatabase()
 */
public SQLiteDatabase getSQLiteDatabase() {
    try {

        sqliteDatabase = SQLiteDatabase.openDatabase(db_path, null,
                SQLiteDatabase.OPEN_READWRITE);
        sqliteDatabase.setVersion(1);
        sqliteDatabase.setLocale(Locale.getDefault());
        sqliteDatabase.setLockingEnabled(true);
        return sqliteDatabase;
    } catch (Exception e) {
        return null;
    }

}

sqlite dbの正確な場所(私の場合はdb_path)を指定すると、上記の方法を使用して、sqliteデータベースを返すかどうかを確認できます。

于 2011-06-10T16:37:43.340 に答える
-1

考えられる解決策は、この方法を使用してデータベースを開くことです

myDataBase = SQLiteDatabase.openDatabase(DATABASE_NAME, null, SQLiteDatabase.OPEN_READWRITE);

テストでデータベース名を変更します。ここでは、このメソッドに関する情報を見つけることができます。

于 2011-01-14T10:31:06.313 に答える