Podczas pisania testów należy wziąć pod uwagę skalowalność. Zastanów się, ile czasu zajęłoby uruchomienie 200 tys. przypadków testowych.
Fragmentacja to jedna z rozwiązań dostępnych w federacji handlu. Wymaga to podziału wszystkich testów potrzebnych do uruchomienia na kilka części, które można przeprowadzić równolegle.
Na tej stronie dowiesz się, jak przekształcić bieg do fragmentacji na potrzeby Tradefed.
Interfejs do implementacji
Najważniejszym interfejsem do wdrożenia, który TF uzna za możliwy do podzielenia na fragmenty, jest IShardableTest, który zawiera 2 metody: split(int numShard)
i split()
.
Jeśli podział na części będzie zależeć od liczby żądanych części, należy zaimplementować split(int numShard)
. W przeciwnym razie wdróż 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 funkcję split
, aby uzyskać nowy obiekt IRemoteTest
, który uruchomi podzbiór przypadków testowych dla konkretnego fragmentu.
Co muszę wiedzieć o przypadku podziału?
- Runner może dzielić się tylko w niektórych warunkach; w takim przypadku zwraca
null
, gdy nie dzieli się. - 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
ma element
ajur-max-shard
, który służy do określania maksymalnej liczby fragmentów, na które można podzielić dane, niezależnie od liczby zażądanych fragmentów.
Szczegółowa przykładowa implementacja
Oto przykładowy fragment kodu implementujący funkcję IShardableTest
, którego możesz użyć. 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;
}
...
}
W tym przykładzie po prostu tworzymy nową instancję i ustawiamy dla niej parametry fragmentacji. Zasady podziału mogą się jednak całkowicie różnić w zależności od testu. Dopóki są deterministyczne i dają w sumie wyczerpujące zbiory, wszystko jest w porządku.
Niepodległość
Fragmenty muszą być niezależne od siebie. Dwa fragmenty utworzone przez implementację split
w Twoim wykonawcy nie powinny być od siebie zależne ani współdzielić zasobów.
Dzielenie fragmentów musi być deterministyczne! Jest to też obowiązkowe, ponieważ w tych samych warunkach metoda split
powinna zawsze zwracać dokładnie tę samą listę fragmentów 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 fragmentów rozdzielonych wywołań, musisz się upewnić, że Twoja usługa raportowania ją obsługuje.