ここからは、これまでの連載同様にテストコードを記述してテストを自動化していきますが、開発中に製品アプリ側で使用しているDBをそのままテストに使用すると、そのときの状態によって実行結果が変わってしまいテストを計画通りに行えません。
そこでテスト実行用のDBを作成すると、共通のテストデータを投入することで毎回計画通りのテストが実行できるようになります。また、これにより連載第6回で予定しているCIサーバによるテストも行いやすくもなります。
Androidにはテスト専用のDBを作成するために、「android.test.RenamingDelegatingContext」クラスがあります。このクラスが「android.test」パッケージに含まることからも、テスト用に提供されていることが分かります。早速、使用例を見てください。
public class SQLiteUserDaoTest extends AndroidTestCase {
private AppOpenHelper helper;
public void setUp() {
super.setUp();
Context context = new RenamingDelegatingContext(getContext(), "test_");
helper = new AppOpenHelper(context);
}
public void tearDown() {
super.tearDown();
helper.close();
}
}
AndroidのSQLiteにアクセスするには、「android.database.sqlite.SQLiteOpenHelper」クラスを継承した実装クラスにandroid.content.Contextを渡す必要があります。RenamingDelegatingContextクラスは名前から推測できるようにContextクラスを継承しています。
RenamingDelegatingContextのインスタンスをSQLiteOpenHelperクラスのコンストラクタに渡すことが可能で、コンストラクタの第1引数にはテストプロジェクトのContextを渡し、第2引数にはテスト用に使用するDBのプレフィックス名を指定します。
SQLiteOpenHelperの実装クラスが「app.db」という名前のDBを生成する場合、今回の例では、テスト実行時にプレフィックスに指定した「test_」が付加された「test_app.db」というファイル名としてDBが作成されます。テストでは、こちらのDBを利用します。これによって、各テストケース実行時に毎回クリーンなDBの状態で開始できます。
なお、テストメソッド間に依存性を持たせないために、RenamingDelegatingContextのインスタンスはテストメソッドごとに1つ作成して、SQLiteOpenHelperに渡すのが基本的に良いでしょう。
実際にJUnitからsetupメソッドでテストデータを登録して、名前の「あいまい検索」を行う処理をテストしてみます。ここでは、「TestCase全体で共通のテストデータを利用する」という前提でsetUpメソッドにテストデータを登録しています。
public class AppOpenHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "app";
private static final int LATEST_VERSION = 1;
public AppOpenHelper(Context context) {
this(context, LATEST_VERSION);
}
public AppOpenHelper(Context context, int version) {
super(context, DB_NAME, null, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table user(_id integer primary key autoincrement, name text, image blob, createdAt integer, updatedAt integer)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table user");
onCreate(db);
}
}
public class SQLiteUserDaoTest extends AndroidTestCase {
private AppOpenHelper helper;
public void setUp() {
helper = new AppOpenHelper(new RenamingDelegatingContext(getContext(), "test_"));
SQLiteDatabase db = helper.getWritableDatabase();
try {
db.execSQL("insert into user(name, createdAt, updatedAt) values ('宮田', 1326361400, 1326361400)");
db.execSQL("insert into user(name, createdAt, updatedAt) values ('渡辺', 1326361400, 1326361400)");
db.execSQL("insert into user(name, createdAt, updatedAt) values ('吉澤', 1326361400, 1326361500)");
db.execSQL("insert into user(name, createdAt, updatedAt) values ('吉沢', 1326361400, 1326561600)");
} finally {
db.close();
}
}
public void tearDown() {
helper.close();
}
public void testFindByName() {
SQLiteDatabase db = helper.getReadableDatabase();
try {
UserDao userDao = new SQLiteUserDao(db);
List<User> users = userDao.findByName("吉");
assertEquals("検索対象件数が一致すること", 2, users.size());
User first = users.get(0);
assertEquals("先頭の名前が一致すること", "吉澤", first.getName());
assertEquals("先頭の作成日時が一致すること", , new Date(1326361400), first.getCreatedAt());
User second = users.get(1);
assertEquals("2 番目のユーザー名が一致すること", "吉沢", second.getName());
assertEquals("2 番目の更新日時が一致すること", new Date(1326561600), second.getUpdatedAt());
} finally {
db.close();
}
}
}
今回は参照のテストを記述しましたが、insert・update・deleteも同じようにテストできます。また単体テストだけではなく、前回の「Androidアプリを“超”魅力的にする3種類のUIテスト」で紹介したような結合テスト以降でも、テストデータを登録して利用可能です。
次ページでは、残りのマイグレーションテストについて解説します
なお筆者は、テストデータの投入をコードで記述することが面倒だと感じたため、「SQLite Fixture Library」というライブラリを作成しました。
このライブラリを使うと、テストプロジェクトにテストデータをCSVまたはYAML形式で記述できます。バイナリデータもBase64エンコード形式の文字列でテストデータを登録できるようにしています。もしテストデータの投入が面倒と感じたら使用してみてください。
Copyright © ITmedia, Inc. All Rights Reserved.
Test & Tools 記事ランキング