Napisz fragment uruchomienia testowego IRemoteTest

Pisząc funkcję uruchamiania testów, należy pamiętać o skalowalności. Zapytaj „Gdyby mój biegacz musiał przeprowadzić 200 tys. testów” ile czasu to zajmie?

Fragmentacja to jedna z rozwiązań dostępnych w federacji handlu. Wymaga podzielić wszystkie potrzebne testy na kilka części, równolegle.

Na tej stronie dowiesz się, jak przekształcić bieg do fragmentacji na potrzeby Tradefed.

Interfejs do implementacji

Najważniejszy interfejs, który należy zaimplementować, aby został uznany za podlegający fragmentacji TF to IShardableTest, który zawiera 2 metody: split(int numShard) i split().

Jeśli fragmentacja będzie zależała od liczby żądanych fragmentów, powinien zaimplementować split(int numShard). W przeciwnym razie zaimplementuj split().

Gdy wykonywane jest polecenie testowe TF z parametrami fragmentacji --shard-count i --shard-index, TF powtarza procedurę przez wszystkie wystąpienia typu IRemoteTest w poszukiwaniu wdrażanie IShardableTest. Jeśli zostanie znaleziony, wywoła wywołanie split do pobierz nowy obiekt IRemoteTest, aby uruchomić podzbiór przypadków testowych dla konkretnego fragment.

Co muszę wiedzieć o przypadku podziału?

  • Biegacz może fragmentować tylko pod pewnymi warunkami. w tym przypadku zwróć null bez fragmentów.
  • Postaraj się podzielić jak najwięcej: i jakąś sensowną pracę. To zależy od biegacza. Dla: przykład: Test Host jest podzielony na fragment na poziomie klasy, każda klasa testowa jest umieszczana w osobnym fragmencie.
  • Jeśli ma to sens, dodaj opcje, aby nieco kontrolować fragmentowanie. Na przykład: AndroidJUnitTest zawiera element ajur-max-shard określający maksymalną liczbę fragmentów, jaką może obsłużyć podzielone niezależnie od żądanej liczby.

Szczegółowa przykładowa implementacja

Oto przykładowy fragment kodu implementującej dyrektywę IShardableTest, odwołania. Pełny kod jest dostępny na stronie (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;
    }
    ...
}

Ten przykład tworzy po prostu nową instancję i ustawia fragment . Jednak logika podziału może być zupełnie inna niż test do przetestowania; dopóki jest ona deterministyczna i przynosi wspólnie zyski szczegółowe podzbiory, nic nie szkodzi.

Niepodległość

Fragmenty muszą być niezależne od siebie. 2 fragmenty utworzone przez Twoją implementację split w Twoim biegunie nie powinno być od siebie zależnych ani udostępniać i zasobami Google Cloud.

Dzielenie fragmentów musi być deterministyczne! Jest to również obowiązkowe, ponieważ tych samych warunków, metoda split powinna zawsze zwracać dokładnie tę samą listę fragmenty w tej samej kolejności.

UWAGA: ponieważ każdy fragment może być uruchamiany w różnych instancjach TF, tak ważne jest, zapewni, że logika split zwróci podzbiory, które wzajemnie się wykluczają, są wyczerpujące w sposób deterministyczny.

Fragmentowanie testu lokalnie

Aby podzielić test na lokalny plik TF, wystarczy dodać opcję --shard-count do w wierszu poleceń.

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

Następnie TF automatycznie utworzy polecenia dla każdego fragmentu i je uruchomi.

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)

Agregacja wyników testu

Ponieważ TF nie agreguje wyników testów w przypadku rozdzielonego wywołań, musisz się upewnić, że Twoja usługa raportowania ją obsługuje.