Android O 遷移測試:Room

谷歌開發者_發表於2017-08-30

640?wx_fmt=gif


640?wx_fmt=jpeg

在之前的一篇文章中,我們介紹了一下構件元件,其中就提到了使用 Room 來進行資料庫操作。但我們也有注意到,如果您錯誤地實施遷移,最嚴重的結果可能會導致您的應用崩潰或丟失使用者資料。


除此之外,Migration.migrate 在編譯時不會檢查在方法中執行的 SQL 語句,這導致了更多的問題。瞭解到這個情況之後,對遷移進行測試就成了一項必做任務。 Room 提供了 MigrationTestHelper 測試工具,這一工具允許您:

  • 在給定的版本中建立一個資料庫

  • 在資料庫上執行一組給定的遷移

  • 驗證資料庫 schema


當然,Room 不會驗證資料庫中的資料本身。這是您需要親自去實現的東西。

以下是您需要了解的有關 Room 遷移測試的內容。



工作原理

640?wx_fmt=png

為了進行遷移測試,Room 需要知道您當前資料庫版本的幾個要素:版本號、Entity、Identity Hash,以及為建立和更新 room_master_table 而做出的查詢請求。所有這些都由 Room 在編譯時自動生成,並儲存在schema JSON 檔案中。


在 build.gradle 檔案中指定一個資料夾,來放置這些生成的 schema JSON 檔案。在更新 schema 時,最終會出現一些 JSON 檔案,每個版本都將有一個對應的檔案。確保將每個生成的檔案提交給原始碼管理工具。下次再次增加版本號碼時,Room 可以使用 JSON 檔案進行測試。



先決條件

要生成 JSON 檔案,請使用以下內容更新 build.gradle 檔案:

1. 定義 schema 位置

defaultConfig {
 javaCompileOptions {
           annotationProcessorOptions {
               arguments = ["room.schemaLocation":
                               "$projectDir/schemas".toString()]
           }
       }
}


2. 將 schema 位置新增到原始碼目錄

android {
   
   sourceSets {
       androidTest.assets.srcDirs +=  
                          files("$projectDir/schemas".toString())
   }


3. 將 Room 測試庫新增到依賴列表中

dependencies {

androidTestImplementation    
               “android.arch.persistence.room:testing:1.0.0-alpha5”
}



遷移測試規則

建立資料庫和 schema,開啟和關閉資料庫,執行遷移 —— 您幾乎需要為每個測試編寫大量這樣的樣板程式碼。為了避免過度重複勞動,請在遷移測試類中使用 MigrationTestHelper 測試工具。


為了建立資料庫以及驗證遷移,MigrationTestHelper 很大程度上依賴於生成的 JSON 檔案。

@Rule
public MigrationTestHelper testHelper =
       new MigrationTestHelper(
               InstrumentationRegistry.getInstrumentation(),
               <your_database_class>.class.getCanonicalName(),
               new FrameworkSQLiteOpenHelperFactory());


您可以在特定版本中建立資料庫:

// Create the database with version 2
SupportSQLiteDatabase db =
                        testHelper.createDatabase(TEST_DB_NAME, 2);


您可以執行一組遷移,並自動驗證 schema 是否更新無誤:

db = testHelper.runMigrationsAndValidate(TEST_DB_NAME, 4, validateDroppedTables, MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4);



實施測試

測試策略很簡單:

  1. 在特定版本中開啟資料庫;

  2. 插入一些資料;

  3. 執行遷移並驗證 schema;

  4. 檢查資料庫中是否有正確的資料。


例如,資料庫的版本 3 新增了一個新列:date 。因此,當測試從版本 2 到版本 3 的遷移時,我們檢查插入到版本 2 的資料的有效性,也是我們新列的預設值。我們的 AndroidJUnitTest 看起來是這樣的:

@Test
public void migrationFrom2To3_containsCorrectData() throws
                                                      IOException {
   // Create the database in version 2
   SupportSQLiteDatabase db =
                        testHelper.createDatabase(TEST_DB_NAME, 2);
   // Insert some data
   insertUser(USER.getId(), USER.getUserName(), db);
   //Prepare for the next version
   db.close();

   // Re-open the database with version 3 and provide MIGRATION_1_2  
   // and MIGRATION_2_3 as the migration process.
   testHelper.runMigrationsAndValidate(TEST_DB_NAME, 3,  
             validateDroppedTables, MIGRATION_1_2, MIGRATION_2_3);

   // MigrationTestHelper automatically verifies the schema  
   //changes, but not the data validity
   // Validate that the data was migrated properly.
   User dbUser = getMigratedRoomDatabase().userDao().getUser();
   assertEquals(dbUser.getId(), USER.getId());
   assertEquals(dbUser.getUserName(), USER.getUserName());
   // The date was missing in version 2, so it should be null in
   //version 3
   assertEquals(dbUser.getDate(), null);
}



測試從 SQLiteDatabase 到 Room 的遷移

從標準 SQLiteDatabase 到 Room 的步驟雖然乍一看很直觀,但我們覺得有必要詳細介紹如何測試遷移實現。


因為原本的資料庫沒有使用 Room 實現,自然我們就沒有相應的 JSON 檔案,因此我們無法使用 MigrationTestHelper 建立資料庫。


我們需要這麼做:

  1. 擴充套件 SQLiteOpenHelper 類,並在 onCreate 執行建立資料庫表的 SQL 查詢操作;

  2. 在 @Before 測試方法中,建立資料庫;

  3. @After 測試方法中,清除資料庫;

  4. 使用 SQLiteOpenHelper ,來插入測試所需的資料,檢查從 SQLiteDatabase 版本遷移到使用 Room 的版本;

  5. 使用 MigrationTestHelper 執行遷移和驗證 schema;

  6. 檢查資料庫資料的有效性。


資料庫版本 1 使用 SQLiteDatabase 實現,然後在版本 2 中,我們遷移到了 Room,而在版本 3 中,我們新增了一個新的列。檢查從版本 1 到 3 的遷移測試如下所示:

@Test
public void migrationFrom1To3_containsCorrectData() throws IOException {
   // Create the database with the initial version 1 schema and    
   //insert a user
   SqliteDatabaseTestHelper.insertUser(1, USER.getUserName(), sqliteTestDbHelper);

   // Re-open the database with version 3 and provide MIGRATION_1_2
   // and MIGRATION_2_3 as the migration process.
   testHelper.runMigrationsAndValidate(TEST_DB_NAME, 3, true,
           MIGRATION_1_2, MIGRATION_2_3);

   // Get the latest, migrated, version of the database
   // Check that the correct data is in the database
   User dbUser = getMigratedRoomDatabase().userDao().getUser();
   assertEquals(dbUser.getId(), 1);
   assertEquals(dbUser.getUserName(), USER.getUserName());
   // The date was missing in version 2, so it should be null in  
   //version 3
   assertEquals(dbUser.getDate(), null);
}



挽起袖子試試吧!

640?wx_fmt=jpeg

這裡有一個示例 App:

https://github.com/googlesamples/android-architecture-components/tree/master/PersistenceMigrationsSample


您可以在此示例應用中檢視實現。為了簡化比較,每個資料庫版本都是以自己的風格實現的,相信看完之後您已經能玩轉典型的遷移路徑了:

  1. sqlite:使用 SQLiteOpenHelper 和傳統的 SQLite 介面;

  2. room :使用 Room 替換實現,並提供到版本 2 的遷移;

  3. room2:將資料庫更新為新 schema,版本 3;

  4. room3 將資料庫更新為新的版本 4。提供從版本 2 到 3,版本 3 到 4,以及版本 1 到 4 的遷移路徑。


640?wx_fmt=jpeg

使用 Room,您可以很容易地實施和測試遷移。MigrationTestHelper 允許您在任何版本開啟資料庫、執行遷移,並且只需幾行程式碼就可以驗證 schema。


您是否已經開始使用 Room 並實施遷移?如果答案是肯定的話,請在下面寫出評論,讓我們瞭解您的想法和問題。



推薦閱讀:

全新 Android 構建元件到底有多好用?

Android 8.0 Oreo 畫中畫模式

Android 8.0 Oreo 現已推出!

Android O 遷移應用官方指南

Android O 行為變更官方指南


640?wx_fmt=gif

相關文章