Tulis pelari pengujian IRemoteTest yang dipecah

Saat menulis test runner, penting untuk memikirkan skalabilitas. Tanyakan pada diri Anda, "jika test runner saya harus menjalankan 200 ribu test case" berapa lama waktu yang dibutuhkan?

Sharding adalah salah satu jawaban yang tersedia di Federasi Dagang. Hal ini memerlukan pemisahan semua tes yang dibutuhkan pelari menjadi beberapa bagian yang dapat diparalelkan.

Halaman ini menjelaskan cara membuat runner Anda dapat disharding untuk Tradefed.

Antarmuka untuk diimplementasikan

Satu-satunya antarmuka terpenting yang perlu diimplementasikan agar dianggap shardable oleh TF adalah IShardableTest , yang berisi dua metode: split(int numShard) dan split() .

Jika sharding Anda akan bergantung pada jumlah shard yang diminta, Anda harus menerapkan split(int numShard) . Jika tidak, terapkan split() .

Ketika perintah pengujian TF dijalankan dengan parameter sharding --shard-count dan --shard-index , TF melakukan iterasi melalui semua IRemoteTest untuk mencari yang mengimplementasikan IShardableTest . Jika ditemukan, ia akan memanggil split untuk mendapatkan objek IRemoteTest baru guna menjalankan subset kasus pengujian untuk pecahan tertentu.

Apa yang harus saya ketahui tentang implementasi terpisah?

  • Anda pelari dapat melakukan shard pada beberapa kondisi saja; dalam hal ini kembalikan null ketika Anda tidak melakukan shard.
  • Cobalah untuk membagi sebanyak yang masuk akal: bagi pelari Anda menjadi unit eksekusi yang masuk akal. Itu sangat tergantung pada pelari Anda. Misalnya: HostTest di-sharding di tingkat Kelas, setiap kelas pengujian ditempatkan di shard terpisah.
  • Jika masuk akal, tambahkan beberapa opsi untuk sedikit mengontrol sharding. Misalnya: AndroidJUnitTest memiliki ajur-max-shard untuk menentukan jumlah maksimum shard yang dapat dipecah, berapa pun jumlah yang diminta.

Contoh implementasi terperinci

Berikut adalah contoh cuplikan kode penerapan IShardableTest yang dapat Anda referensikan. Kode lengkap tersedia di (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;
    }
    ...
}

Contoh ini hanya membuat instance baru dari dirinya sendiri dan menetapkan parameter shard ke dalamnya. Namun, logika pemisahan bisa sangat berbeda dari satu tes ke tes lainnya; dan selama hal tersebut bersifat deterministik dan menghasilkan himpunan bagian yang lengkap secara kolektif, hal tersebut tidak masalah.

Kemerdekaan

Pecahan harus mandiri! Dua pecahan yang dibuat oleh penerapan split di runner Anda tidak boleh memiliki ketergantungan satu sama lain atau berbagi sumber daya.

Pemisahan pecahan harus bersifat deterministik! Ini juga wajib, mengingat kondisi yang sama, metode split Anda harus selalu mengembalikan daftar pecahan yang sama persis dalam urutan yang sama.

CATATAN: Karena setiap shard dapat berjalan pada instance TF yang berbeda, penting untuk memastikan logika split menghasilkan subset yang saling eksklusif dan lengkap secara kolektif dengan cara yang deterministik.

Shard tes secara lokal

Untuk melakukan shard pengujian pada TF lokal, Anda cukup menambahkan opsi --shard-count ke baris perintah.

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

Kemudian TF akan secara otomatis memunculkan perintah untuk setiap pecahan dan menjalankannya.

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)

Agregasi hasil tes

Karena TF tidak melakukan agregasi hasil pengujian apa pun untuk pemanggilan shard, Anda perlu memastikan layanan pelaporan Anda mendukungnya.