編寫分片 IRemoteTest 測試運行程序

編寫測試運行程式時,考慮可擴展性很重要。問問自己,「如果我的測試運行程式必須運行 20 萬個測試案例」需要多長時間?

分片是 Trade Federation 中提供的答案之一。它需要將運行程序所需的所有測試分成幾個可以並行化的區塊。

本頁面介紹如何讓您的運行器可用於 Tradefed 分片。

要實現的介面

要實作 TF 認為可分片的最重要的一個介面是IShardableTest ,它包含兩個方法: split(int numShard)split()

如果您的分片取決於請求的分片數量,您應該實作split(int numShard) 。否則,執行split()

當使用分片參數--shard-count--shard-index執行 TF 測試指令時,TF 會迭代所有IRemoteTest以尋找實作IShardableTest的 IRemoteTest 。如果找到,它將呼叫split來獲取新的IRemoteTest對象,以便為特定分片運行測試案例的子集。

關於拆分實施我應該了解哪些資訊?

  • 您的跑者只能在某些條件下進行分片;在這種情況下,當您沒有分片時傳回null
  • 盡可能嘗試拆分:將運行程序拆分為對其有意義的執行單元。這實際上取決於您的跑步者。例如: HostTest在Class層級進行分片,每個測試類別都放在單獨的分片中。
  • 如果有意義的話,添加一些選項來稍微控制分片。例如: 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 不會對分片呼叫進行任何測試結果聚合,因此您需要確保您的報表服務支援它。