寫入資料分割 IRemoteTest 測試執行器

編寫測試執行程式時,請務必考量擴充性。請自問:「如果測試執行器必須執行 20 萬個測試案例」,需要多久時間?

分割是 Trade Federation 提供的答案之一。這項操作需要將執行程式需要的所有測試分割成可並行執行的多個區塊。

本頁說明如何讓執行程式可供 Tradefed 分割。

要實作的介面

IShardableTest 這個最重要的介面,可將 TF 視為可分割的資料,其中包含以下兩種方法:split(int numShard)split()

如果區塊劃分作業取決於要求的區塊數量,您應實作 split(int numShard)。否則,請實作 split()

當 TF 測試指令搭配使用區隔參數 --shard-count--shard-index 執行時,TF 會逐一檢查所有 IRemoteTest,尋找實作 IShardableTestIRemoteTest。如果找到,就會呼叫 split 取得新的 IRemoteTest 物件,為特定分割區執行一組測試案例。

請問我應該瞭解哪些關於分割導入方式的資訊?

  • 執行器可能只會在某些條件上執行分割;在這種情況下,請在未分割的情況下傳回 null
  • 請盡可能嘗試分段:將執行器分成適當的執行單位。這取決於執行程式。例如:HostTest 是在類別層級進行資料分割,而每個測試類別都會放在獨立的資料分割中。
  • 如果有必要,請新增一些選項來稍微控管分割作業。舉例來說:AndroidJUnitTest 具有 ajur-max-shard 來指定可分割的資料分割數量上限 (無論要求的數量為何)。

詳細導入範例

以下是實作 IShardableTest 的程式碼片段範例,供您參考。完整程式碼可在 (https://android.googlesource.com/platform/tools/tradefederation/+/refs/heads/main/test_framework/com/android/tradefed/testtype/InstalledInstrumentationsTest.java) 中找到

/**
 * Runs all instrumentation found on current device.
 */
@OptionClass(alias = "installed-instrumentation")
public class InstalledInstrumentationsTest
        implements IDeviceTest, IResumableTest, IShardableTest {
    ...

    /** {@inheritDoc} */
    @Override
    public Collection<IRemoteTest> split(int shardCountHint) {
        if (shardCountHint > 1) {
            Collection<IRemoteTest> shards = new ArrayList<>(shardCountHint);
            for (int index = 0; index < shardCountHint; index++) {
                shards.add(getTestShard(shardCountHint, index));
            }
            return shards;
        }
        // Nothing to shard
        return null;
    }

    private IRemoteTest getTestShard(int shardCount, int shardIndex) {
        InstalledInstrumentationsTest shard = new InstalledInstrumentationsTest();
        try {
            OptionCopier.copyOptions(this, shard);
        } catch (ConfigurationException e) {
            CLog.e("failed to copy instrumentation options: %s", e.getMessage());
        }
        shard.mShardIndex = shardIndex;
        shard.mTotalShards = shardCount;
        return shard;
    }
    ...
}

這個範例只會建立本身的新執行個體,並設定其資料分割參數。不過,分割邏輯可能會因測試而異,只要是確定性的邏輯,且能產生完整的子集合,就沒問題。

獨立

資料分割必須獨立!在執行程式中實作 split 時建立的兩個區塊,不應彼此依賴或共用資源。

資料分割須具有確定性!這也是必要條件,在相同條件下,您的 split 方法應一律以相同順序傳回完全相同的切片清單。

注意:由於每個分片都能在不同的 TF 例項上執行,因此務必確保 split 邏輯產生的子集是互斥的,且以確定的方式共同涵蓋所有子集。

在本機分割測試

如要在本機 TF 上分割測試,只要在指令列中加入 --shard-count 選項即可。

tf >run host --class com.android.tradefed.UnitTests --shard-count 3

接著,TF 會自動為每個分割區產生指令並執行。

tf >l i
Command Id  Exec Time  Device          State
3           0m:03      [null-device-2]  running stub on build 0 (shard 1 of 3)
3           0m:03      [null-device-1]  running stub on build 0 (shard 0 of 3)
3           0m:03      [null-device-3]  running stub on build 0 (shard 2 of 3)

測試結果匯總

由於 TF 不會針對資料分割叫用執行任何測試結果匯總,因此您必須確認報表服務支援此做法。