Parçalı IRemoteTest test çalıştırıcısı yazma

Test çalıştırıcı yazarken ölçeklenebilirliği düşünmek önemlidir. "Test çalıştırıcımın 200.000 test örneğini çalıştırması gerekirse ne kadar sürer?" diye kendinize sorun.

Parçalama, Ticaret Federasyonu'nda bulunan yanıtlardan biridir. Bu, çalıştırıcının ihtiyaç duyduğu tüm testlerin paralelleştirilebilecek birkaç parçaya bölünmesini gerektirir.

Bu sayfada, çalıştırıcınızın Tradefed için nasıl parçalara bölünebileceği açıklanmaktadır.

Uygulanacak arayüz

TF tarafından parçalanabilir olarak kabul edilmek için uygulanması gereken en önemli arayüz, split(int numShard) ve split() olmak üzere iki yöntem içeren IShardableTest'tir.

Bölme işleminiz, istenen parça sayısına bağlı olacaksa split(int numShard) uygulamanız gerekir. Aksi takdirde split()'ü uygulayın.

Bir TF test komutu, --shard-count ve --shard-index bölme parametreleriyle yürütüldüğünde TF, IShardableTest'ı uygulayan IRemoteTest öğelerini aramak için tüm IRemoteTest öğelerini iteratif olarak tarar. Bulunursa belirli bir bölüm için test durumlarının bir alt kümesini çalıştırmak üzere yeni bir IRemoteTest nesnesi almak için split çağrılır.

Bölünmüş uygulama hakkında bilmem gerekenler neler?

  • Runner'ınız yalnızca bazı koşullarda parçalara ayırabilir. Bu durumda, parçalara ayırmadığınızda null döndürün.
  • Anlamlı olduğu kadar bölmeye çalışın: Runner'ınızı, kendisi için anlamlı olan bir yürütme birimine bölün. Bu, koşucunuza bağlıdır. Örneğin: HostTest sınıf düzeyinde parçalara ayrılır, her test sınıfı ayrı bir parçaya yerleştirilir.
  • Mantıklıysa parçalamayı biraz kontrol etmek için bazı seçenekler ekleyin. Örneğin: AndroidJUnitTest, istenen sayıdan bağımsız olarak bölünebileceği maksimum parça sayısını belirtmek için bir ajur-max-shard içerir.

Ayrıntılı örnek uygulama

Referans olarak kullanabileceğiniz IShardableTest uygulamasını gösteren örnek bir kod snippet'i aşağıda verilmiştir. Kodun tamamını şu adreste bulabilirsiniz: (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;
    }
    ...
}

Bu örnekte, kendi yeni bir örneği oluşturulur ve bu örnek için bölüm parametreleri ayarlanır. Bununla birlikte, bölme mantığı testten teste tamamen farklı olabilir. Ayrıca deterministik olduğu ve toplu alt kümeler oluşturduğu sürece sorun yoktur.

Bağımsızlık

Parçaların bağımsız olması gerekir. Çalıştırıcınızda split uygulamanız ile oluşturulan iki parçanın birbirine bağımlılığı olmaması veya kaynakları paylaşmaması gerekir.

Parçaların bölünmesi deterministik olmalıdır. Bu da zorunludur. Aynı koşullarda split yönteminiz her zaman aynı sırada tam olarak aynı parça listesini döndürmelidir.

NOT: Her bir parça farklı TF örneklerinde çalışabileceğinden, split mantığının birbirini hariç tutan ve toplu olarak kapsamlı olan alt kümeler sağladığından emin olmak belirleyici bir şekilde önemlidir.

Testi yerel olarak parçalama

Yerel bir TF'de testi bölme işlemini yapmak için komut satırına --shard-count seçeneğini eklemeniz yeterlidir.

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

Ardından TF, her bir parça için otomatik olarak komut oluşturur ve bunları çalıştırır.

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)

Test sonucu toplama

TF, parçalara ayrılmış çağrılar için herhangi bir test sonucu toplama işlemi yapmadığından, raporlama hizmetinizin bunu desteklediğinden emin olmanız gerekir.